我有一个简单的特征,其关联类型没有边界.
trait Board {
type Move;
fn moves(&self) -> Vec<Self::Move>;
}
Run Code Online (Sandbox Code Playgroud)
我也想把这个特性用作超级特征.特别是,我希望我的新子特征对相关类型有更严格的界限.像这样的东西:
trait TextBoard: Board {
type Move: fmt::Debug; // Trying to tighten bounds on associated type
fn printMoves(&self) {
println!("{:?}", self.moves());
}
}
Run Code Online (Sandbox Code Playgroud)
这个例子是高度简化的,但似乎显示了问题:编译器认为我正在尝试创建一个新的关联类型,但我只是想让子文章需要更严格的边界.有没有办法实现这个目标?
这是你要求的:
trait TextBoard: Board
where
Self::Move: Debug,
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
特质的所有界限都必须在"标题"中; 一旦开始编写特征的主体,就不能施加额外的限制.impl TextBoard for Foo当<Foo as Board>::Move没有实现Debug(playground)时,此绑定将阻止您写入.
也许这就是你想要的,但你真的需要阻止TextBoard其他类型的实现吗?对于某些类型,可能有另一种写法print_moves更有意义,而Debug要求只是噪音.在这种情况下,您可能希望跳过该where子句并将主体移动print_moves到毯子impl:
trait TextBoard {
fn print_moves(&self);
}
impl<B: Board> TextBoard for B
where
B::Move: Debug, // or <Self as Board>::Move: Debug
{
fn print_moves(&self) {
println!("{:?}", self.moves());
}
}
Run Code Online (Sandbox Code Playgroud)
使用此版本,您仍然不需要impl为其中的类型编写Self::Move: Debug,但是您不会阻止编写impl其他不适用的类型.它更像是一个扩展,而不是一个改进.
另一方面,你应该总是Debug为每种类型实现,所以具有这种特性真的很有用吗?也许你想要的只是一个可选的方法Board,在以下情况下实现Move: Debug:
trait Board {
type Move;
fn moves(&self) -> Vec<Self::Move>;
fn print_moves(&self)
where
Self::Move: Debug,
{
println!("{:?}", self.moves());
}
}
Run Code Online (Sandbox Code Playgroud)
这与原始版本类似,但不需要添加新TextBoard特征,因此它可能会减少您必须编写的显式边界的数量.许多标准库特性,例如使用这样的Iterator边界定义的可选方法.不足之处,除此之外的要求Move 必须是Debug,是,它杂波的Board特性与印刷代码,你可能不考虑真正的这是什么意思是一个部分Board.
| 归档时间: |
|
| 查看次数: |
197 次 |
| 最近记录: |