Rust中调用Trait约束更强的方法:树结构包含检查实现
Rust 树结构叶子节点包含检查的实现问题
我正在实现一个树结构,包含两种叶子节点:一种存储定长数据,另一种存储变长字符,类型定义如下:
struct Tree<L : Leaf> { parent : L::Item, leaf : L, } struct LeafArr<T> { elements : [T; 8], } struct LeafStr { elements : [u8; 8], } trait Leaf { type Item; } impl<T> Leaf for LeafArr<T> { type Item=T; } impl Leaf for LeafStr { type Item=char; }
在另一个文件中,我想定义一个检查树中是否包含指定项的函数:
impl<L : Leaf> Tree<L> where L::Item : Eq { fn tree_contains(&self, search: &L::Item) -> bool { &self.parent == search || self.leaf.contains(search) // 需要调用对应的contains0方法 } } impl<T : Eq> LeafArr<T> { fn contains0(&self, search : &T) -> bool { for k in 0 .. 8 { if &self.elements[k] == search { return true; } } return false; } } impl LeafStr { fn contains0(&self, search : &char) -> bool { // 为简化问题省略错误处理 for c in unsafe { std::str::from_utf8_unchecked(&self.elements) } .chars() { if &c == search { return true; } } return false; } }
问题核心
如何让self.leaf.contains(search)正确调用对应的contains0方法?contains0要求Item: Eq,但这个约束没有定义在Leaf trait中,不过tree_contains的where子句已经提供了该约束。
约束条件:
- 不接受强制树仅存储实现
Eq的项,因为其他函数无需该约束即可正常工作 - 保证模块化,主文件尽可能少了解子文件的功能
- 理想情况下搜索项类型仅需满足
PartialEq
解决方案
我们可以定义一个带条件约束的关联Trait,既不污染原有的Leaf trait,又能在需要时提供contains能力:
步骤1:定义新的ContainsItem trait
在主文件(或公共模块)中定义这个trait,仅在需要包含检查时使用:
trait ContainsItem: Leaf { fn contains(&self, search: &Self::Item) -> bool; }
步骤2:为叶子节点实现ContainsItem
在子文件中为LeafArr和LeafStr实现该trait,同时加上对应的约束:
// 为LeafArr实现,约束T: PartialEq(替代Eq,更宽松) impl<T: PartialEq> ContainsItem for LeafArr<T> { fn contains(&self, search: &T) -> bool { self.elements.iter().any(|item| item == search) } } // 为LeafStr实现,char本身满足PartialEq impl ContainsItem for LeafStr { fn contains(&self, search: &char) -> bool { unsafe { std::str::from_utf8_unchecked(&self.elements) } .chars() .any(|c| &c == search) } }
步骤3:修改tree_contains的约束
让Tree的tree_contains方法同时约束L实现ContainsItem,并将Eq放宽为PartialEq:
impl<L> Tree<L> where L: ContainsItem, L::Item: PartialEq, // 替换Eq为更宽松的PartialEq { fn tree_contains(&self, search: &L::Item) -> bool { &self.parent == search || self.leaf.contains(search) } }
方案优势
- 模块化:主文件只需要知道
ContainsItemtrait的存在,无需了解具体叶子节点的实现细节 - 无强制约束:原
Leaftrait没有被修改,不需要所有叶子节点都实现ContainsItem或满足PartialEq,其他函数不受影响 - 更宽松的类型约束:使用
PartialEq替代Eq,覆盖更多使用场景(比如浮点数类型也能支持)
内容的提问来源于stack exchange,提问作者DanielV
相关产品推荐
相关产品推荐

