2 个版本
0.1.1 | 2022年2月15日 |
---|---|
0.1.0 | 2021年10月29日 |
#1707 在 Rust 模式
8KB
haz
对多态环境的薄抽象。
动机
考虑一个场景,我们想要将一些数据传递给几个函数。
也许我们有一个类型 Config
来表示我们应用程序的配置,它包含一系列数据(例如 Host
、Port
、Verbosity
、Restriction
以及可能还有许多其他字段)
struct Config {
host: Host,
port: Port,
verbosity: Verbosity,
restriction: Restriction,
// ...
}
我们可能想要将这些数据传递给一些函数,然后这些函数将使用相关的字段来执行一些操作
fn do_something_with_host_port_verbosity(...) {
// ...
}
// ...
我们可以将整个 Config
的引用传递给每个函数
fn do_something_with_host_port_verbosity(cfg: &Config) {
//...
}
// ...
但是,并不是每个函数都需要知道每个字段,我们可能想要避免这种不必要的耦合。
一种方法是为每个需要这些字段的函数显式地传递每个字段
fn do_something_with_host_port_verbosity(host: &Host, port: &Port, restriction: &Restriction) {
// ...
}
// ...
然而,在使用位置可能比较繁琐,因为我们需要逐个传递每个字段
let cfg = read_config();
do_something_with_host_port_verbosity(&cfg.host, &cfg.port, &cfg.verbosity);
我需要数据吗?
haz 的想法是帮助实现这两个目标
- 不要向不需要访问这些数据的函数传递数据
- 不需要逐个传递每个字段
一切围绕薄特质 Has<Component>
浮动
trait Has<Component> {
fn access(&self) -> &Component;
}
通过为某些类型 Container
实现 Has<Component>
,我们声明 Container
可以提供对 Component
的只读访问。
有了这个特质,假设我们已经为 Config
实现了 Has<Host>
、Has<Port>
、Has<Verbosity>
等等(可能使用 impl_has_for_named_component
)的实现,我们可以利用它作为
fn do_something_with_host_port_verbosity<C>(cfg: &C)
where
C: Has<Host> + Has<Port> + Has<Verbosity> {
//...
}
// ...
我们已经明确声明了我们作为 do_something_with_host_port_verbosity
需要什么,因此将获得访问权限——但不是其他任何东西。
在用法位置,它将看起来像
let cfg = read_config();
do_something_with_host_port_verbosity(&cfg);
我们只是传递对 Config
的引用,而不是逐个字段。
总之,我们已经实现了我们的两个目标
- 不要向不需要访问这些数据的函数传递数据
- 不需要逐个传递每个字段