Kir*_*ill 4 factory-method rust
我刚刚学习 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" }
}
Run Code Online (Sandbox Code Playgroud)
我想向此特征添加一个静态方法,以按名称创建一些标准实现:
trait Abstract {
fn new(name: &str) -> Self {
match name {
"foo" => Foo{},
"bar" => Bar{},
"baz" => Baz{},
}
}
fn name(&self) -> &str;
}
Run Code Online (Sandbox Code Playgroud)
但这段代码无法编译,因为:
6 | fn new(name: &str) -> Self {
| ^^^^ doesn't have a size known at compile-time
Run Code Online (Sandbox Code Playgroud)
我尝试使用 returnfn new(name: &str) -> impl Abstract和
fn new<T: Abstract>(name: &str) -> T- 但这些变体对于其他错误也不起作用。
在 Rust 中为特征创建工厂方法的正确方法是什么?
在 Rust 中,每个变量都必须是单一的特定类型。这与 OO 语言不同,在面向对象语言中,变量可以具有类型Foo,这意味着该变量包含Foo或 的任何子类Foo。
Rust 不支持这一点。如果变量具有 type Foo,则它必须包含 a Foo(忽略任何不安全的问题)。
Rust 也不支持使用特征作为类型(没有关键字dyn)。
在您的示例中,您有:
trait Abstract {
fn new(name: &str) -> Self {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
这里的返回类型Self意味着“无论该特征正在实现的类型”。但是,通过在特征定义中提供主体,您将提供默认实现,因此理论上该函数应该适用于任何类型,因此编译器没有有关真实具体类型的信息Self,因此Sized它不满足边界(这在实践中是非常严格的,可能不是你想要的)。
如果您想要一个接受字符串并返回“T实现某种类型Abstract”的函数,您可以使用“特征对象”,它大致如下所示:
// 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 {}),
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我警告不要使用这种模式。动态分派有一些运行时开销,并且会阻止许多编译时优化。相反,可能有一种更“生疏”的方式来做到这一点,但如果没有更多的上下文,很难说清楚。
一般来说,基于字符串的值构建类型有点像反模式。
| 归档时间: |
|
| 查看次数: |
1441 次 |
| 最近记录: |