Rust &引用;“子类化”;锈病特征
我有一种情况,我的几个结构应该实现多个trait,但它们都至少实现了一个共同的trait。当我得到这些结构的混合包时,我希望将它们都视为共同特征:将它们作为键入该特征的方法参数传递,将它们存储在为该特征键入的集合中,等等 我还不知道怎么做。下面是一些代码,我尝试按照此处建议的方式执行,但未能编译:Rust &引用;“子类化”;锈病特征,rust,polymorphism,traits,Rust,Polymorphism,Traits,我有一种情况,我的几个结构应该实现多个trait,但它们都至少实现了一个共同的trait。当我得到这些结构的混合包时,我希望将它们都视为共同特征:将它们作为键入该特征的方法参数传递,将它们存储在为该特征键入的集合中,等等 我还不知道怎么做。下面是一些代码,我尝试按照此处建议的方式执行,但未能编译: trait ThingWithKeys { fn use_keys (&self) -> String; } ////// trait CorrectionsOfficer
trait ThingWithKeys {
fn use_keys (&self) -> String;
}
//////
trait CorrectionsOfficer {
fn hitch_up_pants (&self) -> String;
}
trait CorrectionsOfficerWithKeys: ThingWithKeys + CorrectionsOfficer {}
struct CorrectionsOfficerReal {}
impl ThingWithKeys for CorrectionsOfficerReal {
fn use_keys (&self) -> String {
String::from ("Clank, clank")
}
}
impl CorrectionsOfficer for CorrectionsOfficerReal {
fn hitch_up_pants (&self) -> String {
String::from ("Grunt")
}
}
impl <T: ThingWithKeys + CorrectionsOfficer> CorrectionsOfficerWithKeys for T {}
//////
trait Piano {
fn close_lid (&self) -> String;
}
trait PianoWithKeys: Piano + ThingWithKeys {}
struct PianoReal {}
impl ThingWithKeys for PianoReal {
fn use_keys (&self) -> String {
String::from ("Tinkle, tinkle")
}
}
impl Piano for PianoReal {
fn close_lid (&self) -> String {
String::from ("Bang!")
}
}
impl <T: ThingWithKeys + Piano> PianoWithKeys for T {}
//////
trait Florida {
fn hurricane (&self) -> String;
}
trait FloridaWithKeys: ThingWithKeys + Florida {}
struct FloridaReal {}
impl ThingWithKeys for FloridaReal {
fn use_keys (&self) -> String {
String::from ("Another margarita, please")
}
}
impl Florida for FloridaReal {
fn hurricane (&self) -> String {
String::from ("Ho-hum...")
}
}
impl <T: ThingWithKeys + Florida> FloridaWithKeys for T {}
//////
fn main() {
let corrections_officer_ref: &CorrectionsOfficerWithKeys = &CorrectionsOfficerReal {};
let piano_ref: &PianoWithKeys = &PianoReal {};
let florida_ref: &FloridaWithKeys = &FloridaReal {};
use_keys (corrections_officer_ref);
use_keys (piano_ref);
use_keys (florida_ref);
}
fn use_keys (thing_with_keys: &ThingWithKeys) {
println! ("{}", thing_with_keys.use_keys ());
}
本质上,它仍然无法在XxxWithKeys实现中找到ThingWithKeys实现。Rust中的特征继承不同于OOP继承。特质继承只是一种指定需求的方法<代码>特征B:A并不意味着如果一个类型实现了
B
,它将自动实现A
;这意味着如果一个类型实现B
,它必须实现a
。这也意味着如果实现了B
,则必须单独实现A
例如,
trait A {}
trait B: A {}
struct S;
impl B for S {}
// Commenting this line will result in a "trait bound unsatisfied" error
impl A for S {}
fn main() {
let _x: &B = &S;
}
但是,如果希望某个类型在实现a
和B
时自动实现C
(从而避免手动实现该类型的C
),则可以使用泛型impl
:
impl<T: A + B> C for T {}
泛型方法也适用于类型引用(非特征对象)
同时检查:圣诞快乐!我刚才在操场上试过,但似乎不起作用。也许我做错了。我会告诉你我做了什么,但是StackOverflow对注释中的代码格式做了可怕的事情。无论如何,结果是它仍然抱怨XxxWithKeys不是ThingWithKeys,不能传递到use\u keys方法中。(我知道:我会编辑原来的问题,把我的新代码放进去。)哇。实际上,我刚刚发现了通用方法签名的问题,并收到了关于size的投诉,但我在一百万年内从未想过尝试+?size,因为它是一个引用,引用的大小都是一样的。你有没有理由需要+?大小,或者这只是一个你必须记住的魔法咒语?(顺便说一句,谢谢——现在可以正常工作了。)这是因为泛型类型参数在默认情况下是
大小的。然而,特质类型并非如此。要允许类型参数接受未大小(trait)类型,必须添加未大小(?Sized
)绑定。此外,类型参数绑定到引用的类型,而不是引用本身。
impl<T: Florida + ThingWithKeys> FloridaWithKeys for T {}
fn use_keys<T: ThingWithKeys + ?Sized>(thing_with_keys: &T) {
println! ("{}", thing_with_keys.use_keys ());
}