我有以下特点:
use std::ops::Index;
trait Map: Index<<Self as Map>::Key> {
type Key;
}
Index
具有关联的类型Output
。我在语义上想要这种类型,但我不喜欢我的API中的名称Output
。因此,我想为该类型添加别名。
我试过这个(普通类型别名的语法相同):
trait Map: Index<<Self as Map>::Key> {
type Key;
type Value = <Self as Index<Self::Key>>::Output;
}
但是,这会导致错误:
error[E0658]: associated type defaults are unstable (see issue #29661)
--> src/main.rs:9:9
|
9 | type Value = <Self as Index>::Output;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
从the tracking issue我可以收集到这个语法显然用于可以被实现者覆盖的关联类型。但是我不希望实现者覆盖这种类型,我总是想要Map::Value == Map::Output
。
这有可能吗?
答案 0 :(得分:2)
对特征的类型参数可以是“输入”或“输出”:
输入。 “input”类型参数用于确定要使用的impl。
输出。 “输出”类型参数由impl唯一确定,但在选择impl时不起作用。
RFC还通过以下方式阐明了特征匹配:
- 将所有特征类型参数视为输入类型,并
- 提供相关类型,即输出类型。
从这些描述可以清楚地看出,关联类型是由impl
设计控制的,因此无法阻止实现者覆盖该类型。
获取对实现者的某种形式的控制的解决方法可能是定义使用关联类型的默认方法,例如:
pub trait Map: Index<<Self as Map>::Key> {
type Key;
type Value = <Self as Index<<Self as Map>::Key>>::Output;
#[doc(hidden)]
fn invalid_operation() -> Option<&'static <Self as Index<<Self as Map>::Key>>::Output> {
None
}
}
现在,实现者不可能简单地覆盖默认的Value
类型,因为默认方法invalid_operation
不再是类型检查。
还请注意从文档中删除默认方法的doc(hidden)
功能。
可以选择隐藏的方法名称来传达一些信息。 对于上面的示例,实现者会收到错误消息:
error[E0399]: the following trait items need to be reimplemented as `Value` was overridden: `invalid_operation`
如您所知,在当前稳定的Rust中不允许分配默认关联类型,必须使用每晚版本并且必须启用该功能:
#![feature(associated_type_defaults)]