gpt4 book ai didi

rust - 特征的静态工厂方法

转载 作者:行者123 更新时间:2023-12-05 08:24:50 25 4
gpt4 key购买 nike

我只是在学习 Rust,所以可能我只是没有正确理解一些概念。

我有一些实现的特点:

trait Abstract {
fn name(&self) -> &str;
}

struct Foo {}
struct Bar {}
struct Baz {}

impl Abstract for Foo {
fn name(&self) -> &str { "foo" }
}
impl Abstract for Bar {
fn name(&self) -> &str { "bar" }
}
impl Abstract for Baz {
fn name(&self) -> &str { "baz" }
}

我想给这个 trait 添加一个静态方法来按名称创建一些标准实现:


trait Abstract {
fn new(name: &str) -> Self {
match name {
"foo" => Foo{},
"bar" => Bar{},
"baz" => Baz{},
}
}
fn name(&self) -> &str;
}

但这段代码无法编译,因为:

6 |     fn new(name: &str) -> Self {
| ^^^^ doesn't have a size known at compile-time

我尝试使用 return fn new(name: &str) -> impl Abstractfn new<T: Abstract>(name: &str) -> T - 但这些变体不适用于其他错误。

在 Rust 中为特征创建工厂方法的正确方法是什么?

最佳答案

在 Rust 中,每个变量都必须是单一的特定类型。这与 OO 语言不同,其中变量可以具有类型 Foo,这意味着变量包含 FooFoo 的任何子类>.

Rust 不支持这个。如果一个变量的类型是 Foo,它必须包含一个 Foo(忽略任何不安全的问题)。

Rust 也不支持使用特征作为类型(没有 dyn 关键字)。

在你的例子中,你有:

trait Abstract {
fn new(name: &str) -> Self {
// ...
}
}

此处的返回类型Self 表示“该特征正在实现的任何类型”。但是,通过在 trait 定义中提供一个主体,您提供了一个默认实现,因此理论上该函数应该适用于任何类型,因此编译器没有关于真正的具体类型 Self 的信息,因此 Sized 限制了它不满足(这在实践中是非常严格的,可能不是你想要的)。

如果你想要一个接受字符串并返回“实现Abstract的某种类型T”的函数,你可以使用一个“trait object”,它看起来大致喜欢:

// outside trait definition
fn new_abstract(name: &str) -> Box<dyn Abstract> { // dyn keyword opts into dynamic dispatch with vtables
match name {
"foo" => Box::new(Foo {}),
// ...
}
}

但是,我要警告不要使用这种模式。动态分派(dispatch)有一些运行时开销,并阻止了许多编译时优化。相反,可能有一种更“使用rust ”的方式来做这件事,但如果没有更多的上下文,很难说清楚。

一般来说,根据字符串的值构造类型有点反模式。

关于rust - 特征的静态工厂方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70693404/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com