改进rust代码的35种具体方法-类型(二十二)-最小化可见度

本文主要是介绍改进rust代码的35种具体方法-类型(二十二)-最小化可见度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一篇文章 改进rust代码的35种具体方法-类型(二十一)-熟悉Cargo.toml版本使用


Rust允许将代码元素隐藏或暴露给代码库的其他部分。本项目探讨了为此提供的机制,并就应在何时何地使用它们提出建议。

可见性语法

Rust的基本可见性单位是模块。默认情况下,模块的项目(类型、方法、常量)是私有的,只能访问同一模块及其子模块中的代码。

需要更广泛可用的代码用pub关键字标记,使其向其他范围公开。对于大多数Rust语法功能,使功能pub不会自动公开内容——pub mod中的类型和功能不是公开的,也不是pub struct中的字段。然而,有几个例外情况是,将可见性应用于内容是有意义的:

  • 公开枚举会自动使类型的变体也公开(以及这些变体中可能存在的任何字段)。
  • 公开trait会自动公开该特征的方法。

因此,模块中的类型集合:

pub mod somemodule {// Making a `struct` public does not make its fields public.#[derive(Debug, Default)]pub struct AStruct {// By default fields are inaccessible.count: i32,// Fields have to be explicitly marked `pub` to be visible.pub name: String,}// Likewise, methods on the struct need individual `pub` markers.impl AStruct {// By default methods are inaccessible.fn canonical_name(&self) -> String {self.name.to_lowercase()}// Methods have to be explicitly marked `pub` to be visible.pub fn id(&self) -> String {format!("{}-{}", self.canonical_name(), self.count)}}// Making an `enum` public also makes all of its variants public.#[derive(Debug)]pub enum AnEnum {VariantOne,// Fields in variants are also made public.VariantTwo(u32),VariantThree { name: String, value: String },}// Making a `trait` public also makes all of its methods public.pub trait DoSomething {fn do_something(&self, arg: i32);}
}

允许访问pub的东西和前面提到的例外情况:

use somemodule::*;let mut s = AStruct::default();
s.name = "Miles".to_string();
println!("s = {:?}, name='{}', id={}", s, s.name, s.id());let e = AnEnum::VariantTwo(42);
println!("e = {e:?}");#[derive(Default)]
pub struct DoesSomething;
impl DoSomething for DoesSomething {fn do_something(&self, _arg: i32) {}
}let d = DoesSomething::default();
d.do_something(42);

但非pub的东西通常无法进入:

let mut s = AStruct::default();
s.name = "Miles".to_string();
println!("(inaccessible) s.count={}", s.count);
println!("(inaccessible) s.canonical_name()={}", s.canonical_name());
error[E0616]: field `count` of struct `somemodule::AStruct` is private--> src/main.rs:230:45|
230 |     println!("(inaccessible) s.count={}", s.count);|                                             ^^^^^ private field
error[E0624]: method `canonical_name` is private--> src/main.rs:231:56|
86  |         fn canonical_name(&self) -> String {|         ---------------------------------- private method defined here
...
231 |     println!("(inaccessible) s.canonical_name()={}", s.canonical_name());|                                         private method ^^^^^^^^^^^^^^
Some errors have detailed explanations: E0616, E0624.
For more information about an error, try `rustc --explain E0616`.

最常见的可见性标记是裸露的pub关键字,它使该项目对任何能够看到它所在的模块的东西可见。最后一个细节很重要:如果asomecratesomecrate::somemodule模块首先对其他代码不可见,那么它里面的任何pub仍然不可见。

然而,pub也有一些更具体的变体,允许限制可见性的范围。按有用性降序排列,如下所示:

如果您有一个对模块私有但未在该模块(及其子模块)中使用的代码项,Rust编译器将警告您:

pub mod anothermodule {// Private function that is not used within its module.fn inaccessible_fn(x: i32) -> i32 {x + 3}
}

虽然警告表示代码在其拥有的模块中“从未使用过”,但在实践中,此警告通常表明代码不能从模块外部使用,因为可见性限制不允许:

warning: function `inaccessible_fn` is never used--> src/main.rs:56:8|
56 |     fn inaccessible_fn(x: i32) -> i32 {|        ^^^^^^^^^^^^^^^|= note: `#[warn(dead_code)]` on by default

可见性语义

与如何提高知名度的问题不同,是何时这样做的问题。对此普遍接受的答案尽可能少,至少对于任何将来可能被使用和重复使用的代码。

提出这个建议的第一个原因是,可见性的变更很难撤销。一旦一个 crate 项是公共的,就不能再将其设置为私有,否则会破坏使用 crate 的任何代码,从而需要进行主要版本的升级。相反,事实并非如此:将私人项目移动为公共项目通常只需要一个次要版本颠簸,并且不会让板条箱用户不受影响——阅读Rust的API兼容性指南,并注意只有当有pub项目在起作用时,才会注意到有多少是相关的。

一个更重要但更微妙的偏爱隐私的理由是,它让你的选择保持开放。暴露的东西越多,未来需要固定的东西就越多(没有不兼容的变化)。如果您公开数据结构的内部实现细节,那么未来使用更高效算法的假定更改将成为突破性更改。如果您公开内部助手函数,一些外部代码将不可避免地取决于这些函数的确切细节。

当然,这只适用于可能具有多个用户且寿命较长的库代码。但没有什么比临时解决方案更永久的了,所以这是一个好习惯。

同样值得注意的是,这种限制可见性的建议绝不是这个项目或Rust所独有的:

这篇关于改进rust代码的35种具体方法-类型(二十二)-最小化可见度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1064071

相关文章

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

java之Objects.nonNull用法代码解读

《java之Objects.nonNull用法代码解读》:本文主要介绍java之Objects.nonNull用法代码,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录Java之Objects.nonwww.chinasem.cnNull用法代码Objects.nonN

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Java中&和&&以及|和||的区别、应用场景和代码示例

《Java中&和&&以及|和||的区别、应用场景和代码示例》:本文主要介绍Java中的逻辑运算符&、&&、|和||的区别,包括它们在布尔和整数类型上的应用,文中通过代码介绍的非常详细,需要的朋友可... 目录前言1. & 和 &&代码示例2. | 和 ||代码示例3. 为什么要使用 & 和 | 而不是总是使

Java强制转化示例代码详解

《Java强制转化示例代码详解》:本文主要介绍Java编程语言中的类型转换,包括基本类型之间的强制类型转换和引用类型的强制类型转换,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录引入基本类型强制转换1.数字之间2.数字字符之间引入引用类型的强制转换总结引入在Java编程语言中,类型转换(无论

Vue 调用摄像头扫描条码功能实现代码

《Vue调用摄像头扫描条码功能实现代码》本文介绍了如何使用Vue.js和jsQR库来实现调用摄像头并扫描条码的功能,通过安装依赖、获取摄像头视频流、解析条码等步骤,实现了从开始扫描到停止扫描的完整流... 目录实现步骤:代码实现1. 安装依赖2. vue 页面代码功能说明注意事项以下是一个基于 Vue.js

Python如何查看数据的类型

《Python如何查看数据的类型》:本文主要介绍Python如何查看数据的类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python查看数据的类型1. 使用 type()2. 使用 isinstance()3. 检查对象的 __class__ 属性4.