Rust设计模式:sealed trait

2024-04-28 10:06:59 浏览数 (2)

最近升级之前写的一个oauth2 相关[1]的依赖时(深度解读-如何用keycloak管理external auth), 发现新版oauth2-rs[2]有些实现 pattern 很有意思,可以展开看看。

今天先看下sealed trait

这种 pattern 是用来当自己的 trait 想限定一些实现方法时使用。

常规的 trait 定义都是很灵活的,不限定实现

比如下边nosealed_trait可以分别为usizei32实现。

代码语言:javascript复制
mod nosealed_trait {
    pub trait MyTrait {
        fn my_sealed_method(&self);
    }
}
impl nosealed_trait::MyTrait for usize {
    fn my_sealed_method(&self) {
        println!("MyTrait for usize");
    }
}

impl nosealed_trait::MyTrait for i32 {
    fn my_sealed_method(&self) {
        println!("MyTrait for i32");
    }
}

那如果只想为i32实现呢?

可以让自己trait依赖一个不暴露的super trait,由super trait限定能有哪些实现

代码语言:javascript复制
mod sealed_trait {
    mod private {
        pub trait Sealed {}
        impl Sealed for i32 {}
    }
    pub trait MySealedTrait: private::Sealed {
        fn my_sealed_method(&self);
    }
}

impl sealed_trait::MySealedTrait for i32 {
    fn my_sealed_method(&self) {
        println!("MySealedTrait for i32");
    }
}

如果调用方想实现不在限定实现列表中的方法就会被编译错误阻止。

代码语言:javascript复制
impl sealed_trait::MySealedTrait for usize {
    fn my_sealed_method(&self) {
        println!("MySealedTrait for usize");
    }
}

错误如下, 其中的note说的很明白。

note: MySealedTrait is a "sealed trait", because to implement it you also need to implement sealedtrait::private::Sealed, which is not accessible; this is usually done to force you to use one of the provided types that already implement it

代码语言:javascript复制
error[E0277]: the trait bound `usize: Sealed` is not satisfied
  --> src/main.rs:34:37
   |
34 | impl sealedtrait::MySealedTrait for usize {
   |                                     ^^^^^ the trait `Sealed` is not implemented for `usize`
   |
   = help: the trait `Sealed` is implemented for `i32`
note: required by a bound in `MySealedTrait`
  --> src/main.rs:23:30
   |
23 |     pub trait MySealedTrait: private::Sealed {
   |                              ^^^^^^^^^^^^^^^ required by this bound in `MySealedTrait`
   = note: `MySealedTrait` is a "sealed trait", because to implement it you also need to implement `sealedtrait::private::Sealed`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it
   = help: the following type implements the trait:
             i32

下一篇再聊聊typestate pattern.

参考资料

[1]

oauth2 相关: https://github.com/NewbMiao/axum-koans/

[2]

oauth2-rs: https://github.com/ramosbugs/oauth2-rs

0 人点赞