Rust 如何在铁锈中实现抽象工厂?

Rust 如何在铁锈中实现抽象工厂?,rust,Rust,比如: 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");

比如:

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();
}

尝试在不同的位置附加大小,但都失败。

Thingy
是一种特性时,这:

fn make(&self) -> Thingy;
相当于:

fn make(&self) -> dyn Thingy;
也就是说,一个没有大小的裸特征对象。你不能处理像Rust这样大小不一的类型;trait对象需要位于某种指针的后面。假设函数创建了对象,那么它不能是
&dyn Thingy
,因此您需要一个自己的指针,比如
Box

因此,您的
工厂特性将如下所示:

trait Factory {
    fn make(&self) -> Box<dyn Thingy>;
}
impl Factory for AFactory {
    fn make(&self) -> Box<dyn Thingy> {
        Box::from(AThingy{})
    }
}
trait工厂{
fn制造(&self)->包装盒;
}
实现如下所示:

trait Factory {
    fn make(&self) -> Box<dyn Thingy>;
}
impl Factory for AFactory {
    fn make(&self) -> Box<dyn Thingy> {
        Box::from(AThingy{})
    }
}
工厂的impl工厂{
fn制造(&self)->框{
Box::from(AThingy{})
}
}

考虑到您的问题,我猜您正在尝试应用您习惯于使用的面向对象语言(如Java)的模式。这些模式与Rust中常用的习惯用法背道而驰,迫使您装箱数据,否则可能不需要装箱。在Java中,几乎所有的泛型都是装箱的,您需要为此付费。

您可以使用关联的类型<代码>工厂
可以有一个名为
输出
的关联类型。您可以添加一个需要
输出
的绑定来实现
内容

trait工厂{
类型输出:Thingy;
fn make(&self)->self::Output;
}
现在,
a工厂
输出
将是
一个字符串

工厂的impl工厂{
类型输出=一个字符串;
fn制造(和自身)->Ashingy{
AThingy{}
}
}
b工厂
输出
将是
b重量

BFactory的impl工厂{
类型输出=b重量;
fn制造(和自)->b重量{
b小{}
}
}
正如@PeterHall所提到的,您无法处理Rust中的非大小类型,因此要存储
工厂
,您需要使用一个自己的指针,如

#[测试]
fn测试工厂(){
让aFactory:Box=Box::new(aFactory{});
让bFactory:Box=Box::new(bFactory{});
factory.make().hallo();
b factory.make().hallo();
}
但是,由于
工厂
具有关联类型,因此在将其设置为特征对象时,还必须指定
输出

#[测试]
fn测试工厂(){
设aFactory:Box=aFactory{};
设bFactory:Box=bFactory{};
factory.make().hallo();
b factory.make().hallo();
}

如果你是工厂特征,实现一个返回特征的函数?你需要让你的工厂方法返回一个
,或者让它构建的东西的类型成为工厂的关联类型。是的,可以!非常感谢。顺便说一句,>你不能处理非大小的类型,比如-我是否正确理解,这是因为当struct具有Traits(未大小)的函数时,rust无法构建vtable,并且它将被修复?是的,我来自java:)那么,对于抽象工厂来说,什么才是合适的rust习惯用法?@user656449工厂仍然是有效的rust模式,但是,正如我在回答中所解释的那样,它们通常被建模为一种具有相关的
输出的特征。