如何处理动态结构实例化?

问题描述 投票:0回答:1

我有许多实现特征的结构,并且我需要一个函数根据运行时条件返回其中一个结构的实例。我也很难找出

new()
方法的签名,但我猜这两个是相关的。

结构体定义示例

trait Example {
    fn new<T>() -> T where T: Example;

    fn do_something(&self) {
        //something to do
    }
}

struct Ex1 {
    some_attr: String
}

struct Ex2 {
    some_attr: String
}

impl Example for Ex1 {
    fn new<T>() -> T where T: Example {
        Ex1{ some_attr: "".to_string() }
    }
}

impl Example for Ex2 {
    fn new<T>() -> T where T: Example {
        Ex2{ some_attr: "".to_string() }
    }
}

主要/功能示例

fn conditionally_generate_struct() -> Box<dyn Example> {
    let condition = true;
    return if condition {
        Ex1::new()
    } else {
        Ex2::new()
    }
}

let example = conditionally_generate_struct();
example.do_something();

在研究它时,我发现了一些方法,例如使用

Box
T
,但我不完全理解如何使用它们。说实话,我什至不知道如何归类这个问题。难道是泛型概念解决的问题?

在 Rust 中正确的做法是什么?我缺少什么概念?

oop generics rust
1个回答
0
投票
trait Example {
    fn new<T>() -> T where T: Example;
    // ...
}

您(几乎肯定)不希望这样:这意味着可以在调用站点要求任何实现特征

Example
的类型返回也实现
Example
的任何其他类型。例如:

struct Foo; impl Example for Foo { ... }
struct Bar; impl Example for Bar { ... }

// callsite
let foo = Foo;
let bar: Bar = foo.new::<Bar>();

那会很奇怪。所以一般来说,这种方法就是你想要使用

Self
的地方,它是一种代表“当前类型”的类型,即写在
impl
块顶部的类型。

trait Example {
    fn new() -> Self;
}

struct Foo;
impl Example for Foo {
    fn new() -> Self { Foo }
}
struct Bar;
impl Example for Bar {
    fn new() -> Self { Bar }
}

然而,在这种特定情况下,

new
似乎完全没有必要,除非你的代码库中有一些你没有在OP中解释的内容。这是因为没有实际的共享行为:它只是结构的构造。当你可以简单地调用
<Foo as Example>::new()
甚至直接构造
Foo::new()
时,为什么要调用
Foo { .. }
呢?结果是一样的。

对于你问题的第二部分:

fn conditionally_generate_struct() -> Box<dyn Example> {
    let condition = true;
    if condition {
        Box::new(Ex1 { .. })
    } else {
        Box::new(Ex2 { .. })
    }
}

let example = conditionally_generate_struct();
example.do_something();

要返回

Box
,您需要实际构造一个
Box
。实现特征的结构不会自动转换为盒装特征对象,因为这可能是一把枪。

还要再次注意,结构是直接构造的,而不是调用不必要的特征方法。

© www.soinside.com 2019 - 2024. All rights reserved.