就像是:
trait Thingy {
fn hallo(&self);
}
trait Factory {
fn make(&self) -> Thingy;
}
//------------------------------
struct AThingy {}
impl Thingy for AThingy {
fn hallo(&self) {
println!("i'm A thingy");
}
}
struct AFactory {}
impl Factory for AFactory {
fn make(&self) -> AThingy {
AThingy{}
}
}
//------------------------------
struct BThingy {}
impl Thingy for BThingy {
fn hallo(&self) {
println!("i'm B thingy");
}
}
struct BFactory {}
impl Factory for BFactory {
fn make(&self) -> BThingy {
BThingy{}
}
}
//------------------------------
#[test]
fn test_factory() {
let aFactory:Factory = AFactory{};
let bFactory:Factory = BFactory{};
aFactory.make().hallo();
bFactory.make().hallo();
}
Run Code Online (Sandbox Code Playgroud)
试图在不同的地方附加 Sized 但都失败了。
什么时候Thingy是一个特质,这个:
fn make(&self) -> Thingy;
Run Code Online (Sandbox Code Playgroud)
相当于:
fn make(&self) -> dyn Thingy;
Run Code Online (Sandbox Code Playgroud)
也就是说,一个未调整大小的裸特征对象。你不能像 Rust 那样处理未定义大小的类型;特征对象需要位于某种类型的指针后面。鉴于该函数创建对象,它不能是 a &dyn Thingy,因此您需要一个拥有的指针,例如Box<dyn Thingy>。
所以你的Factory特质看起来像这样:
trait Factory {
fn make(&self) -> Box<dyn Thingy>;
}
Run Code Online (Sandbox Code Playgroud)
实现如下所示:
impl Factory for AFactory {
fn make(&self) -> Box<dyn Thingy> {
Box::from(AThingy{})
}
}
Run Code Online (Sandbox Code Playgroud)
鉴于您的问题,我猜您正在尝试应用您习惯的面向对象语言(例如 Java)的模式。这些模式违背了 Rust 中常用的习惯用法,并迫使您对数据进行装箱,否则这些数据可能不需要装箱。在 Java 中,几乎所有通用的东西都被装箱了,并且你为此付出了代价。
您可以使用关联类型。Factory可以有一个关联的类型,称为Output. 您可以添加需要Output实现的边界Thingy:
trait Factory {
type Output: Thingy;
fn make(&self) -> Self::Output;
}
Run Code Online (Sandbox Code Playgroud)
现在AFactory的Output将是AThingy:
impl Factory for AFactory {
type Output = AThingy;
fn make(&self) -> AThingy {
AThingy {}
}
}
Run Code Online (Sandbox Code Playgroud)
和BFactory的Output将是BThingy:
impl Factory for BFactory {
type Output = BThingy;
fn make(&self) -> BThingy {
BThingy {}
}
}
Run Code Online (Sandbox Code Playgroud)
正如@PeterHall 提到的,您无法在 Rust 中处理未定义大小的类型,因此要存储 aFactory您需要使用拥有的指针,例如Box<dyn Factory>:
#[test]
fn test_factory() {
let aFactory: Box<dyn Factory> = Box::new(AFactory {});
let bFactory: Box<dyn Factory> = Box::new(BFactory {});
aFactory.make().hallo();
bFactory.make().hallo();
}
Run Code Online (Sandbox Code Playgroud)
但是,因为Factory有关联类型,所以Output在将其放入特征对象时还必须指定:
#[test]
fn test_factory() {
let aFactory: Box<dyn Factory<Output = AThingy>> = AFactory {};
let bFactory: Box<dyn Factory<Output = BThingy>> = BFactory {};
aFactory.make().hallo();
bFactory.make().hallo();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
324 次 |
| 最近记录: |