Rust语言-接口设计的建议之受约束(Constrained)RustAPI指南GitHub:https://github.com/rust-lang/api-guidelinesRustAPI指南中文:https://rust-chinese-translation.gith
例子一:
pub mod outer_mod {
pub mod inner_mod {
// This function is visible within `outer_mod`
pub(in crate::outer_mod) fn outer_mod_visible_fn() {}
// This function is visible to the entire crate
pub(crate) fn crate_visible_fn() {}
// This function is visible within `outer_mod`
pub(super) fn super_mod_visible_fn() {
// This function is visible since we're in the same `mod`
inner_mod_visible_fn();
}
// This function is visible only within `inner_mod`,
// which is the same as leaving it private.
pub(self) fn inner_mod_visible_fn() {}
}
pub fn foo() {
inner_mod::outer_mod_visible_fn();
inner_mod::crate_visible_fn();
inner_mod::super_mod_visible_fn();
// This function is no longer visible since we're outside of `inner_mod`
// Error! `inner_mod_visible_fn` is private
// inner_mod::inner_mod_visible_fn();
}
}
fn bar() {
// This function is still visible since we're in the same crate
outer_mod::inner_mod::crate_visible_fn();
// This function is no longer visible since we're outside of `outer_mod`
// Error! `super_mod_visible_fn` is private
outer_mod::inner_mod::super_mod_visible_fn();
// This function is no longer visible since we're outside of `outer_mod`
// Error! `outer_mod_visible_fn` is private
outer_mod::inner_mod::outer_mod_visible_fn();
outer_mod::foo();
}
fn main() {
bar()
}
例子二:
lib.rs
pub struct Unit;
main.rs
fn main() {
let u = constrained::Unit; // v0 库是 constrained
}
修改一
lib.rs
pub struct Unit {
pub field: bool,
}
main.rs
fn is_true(u: constrained::Unit) -> bool {
matches!(u, constrained::Unit { field: true })
}
fn main() {
let u = constrained::Unit; // v0 报错,因为添加字段之后 Unit struct 原有的构造方式不可用
}
修改二
lib.rs
pub struct Unit {
local: i32, // 增加私有字段
}
main.rs
fn main() {
let u = constrained::Unit; // v0 报错,虽然字段看不见,但是编译器可以看到
}
#[non_exhaustive]
来缓解这些问题
non_exhaustive
表示类型或枚举在将来可能会添加更多字段或变体non_exhaustive
定义的类型,编译器会禁止:lib::Unit { field1: true }
例子三:
lib.rs
#[non_exhaustive]
pub struct Config {
pub window_width: u16,
pub window_height: u16,
}
fn SomeFunction() {
let config = Config {
window_width: 640,
window_height: 480,
};
// Non-exhaustive structs can be matched on exhaustively within the defining crate.
if let Config {
window_width,
window_height,
} = config
{
// ...
}
}
main.rs
use constrained::Config;
fn main() {
// Not allowed.
let config = Config { // 报错
window_width: 640,
window_height: 480,
};
if let Config {
window_width,
window_height,
.. // This is the only difference. 必须加 .. 否则报错
} = config
{
// ...
}
}
impl <T> Foo for T
)例子四:
lib.rs
pub struct Unit;
pub trait Fool {
fn foo(&self);
}
main.rs
use constrained::{Foo1, Unit};
trait Foo2 {
fn foo(&self);
}
impl Foo2 for Unit {
fn foo(&self) {
println!("foo2");
}
}
fn main() {
Unit.foo()
}
修改一
lib.rs
pub struct Unit;
pub trait Fool {
fn foo(&self);
}
// case 1: Add impl Foo1 for Unit in this crate
impl Foo1 for Unit {
fn foo(&self) {
println!("foo1");
}
}
main.rs
use constrained::{Foo1, Unit};
trait Foo2 {
fn foo(&self);
}
impl Foo2 for Unit {
fn foo(&self) {
println!("foo2");
}
}
fn main() {
Unit.foo() // 报错
}
修改二
lib.rs
pub struct Unit;
pub trait Fool {
fn foo(&self);
}
// case 2: Add a new public Trait
pub trait Bar1 {
fn foo(&self); // with the same name
}
impl Bar1 for Unit {
fn foo(&self) {
println!("bar1");
}
}
main.rs
use constrained::{Foo1, Unit};
trait Foo2 {
fn foo(&self);
}
impl Foo2 for Unit {
fn foo(&self) {
println!("foo2");
}
}
fn main() {
Unit.foo() // 因为没有引入lib.rs中的Bar1,所以暂时没有报错
}
main.rs
use constrained::*;
trait Foo2 {
fn foo(&self);
}
impl Foo2 for Unit {
fn foo(&self) {
println!("foo2");
}
}
fn main() {
Unit.foo() // 报错
}
例子五:
lib.rs
use std::fmt::{Debug, Display};
mod sealed {
use std::fmt::{Debug, Display};
pug trait Sealed {}
impl<T> Sealed for T where T: Debug + Display {}
}
pub trait CanUseCannotImplement: sealed::Sealed {
// ..
}
impl<T> CanUseCannotImplement for T where T: Debug + Display {}
main.rs
use std::fmt::{Debug, Display};
use constrained::CanUseCannotImplement;
pub struct Bar {}
impl Debug for Bar {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(())
}
}
impl Display for Bar {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(())
}
}
// impl CanUseCannotImplement for Bar {} // 报错 因为在 lib.rs 中已经实现好了,不能再实现
// Conflicting implementation,
// The trait `CanUseCannotImplement` has been already implemented
// for the types that satisfy the bounds specified by the sealed trait which are `Debug + Display`
pub struct Foo {}
impl CanUseCannotImplement for Foo {} // 报错 没有实现 Debug 和 Display
fn main() {}
例子六:
lib.rs
// 你的 crate,叫 bestiter
pub fn iter<T>() -> itercrate::Empty<T> { .. }
// 依赖的外部 crate,叫 itercrate (v1.0),提供了 Empty<T> 类型
// 用户的 crate 中
struct EmptyIterator { it: itercrate::Empty<()> }
EmptyIterator { it: bestiter::iter() }
// ---------------------------------------------------------------
// 你的 crate, 叫 bestiter
pub fn iter<T>() -> itercrate::Empty<T> { .. }
// 依赖的外部crate,叫 itercrate,提供了 Empty<T> 类型
// 依赖的版本改为 v2.0,别处没有更改
// 编译器认为:itercrate1.0::Empty 和 itercrate2.0::Empty 是不同的类型
// 导致破坏性变更
// 用户的 crate 中
struct EmptyIterator { it: itercrate::Empty<()> }
例子七:
fn is_normal<T: Sized + Send + Sync + Unpin>() {}
#[test]
fn normal_types() {
is_normal::<MyType>();
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!