当前位置: 首页 > 知识库问答 >
问题:

不同具体类型泛型的Vec重复]

章承基
2023-03-14

我有一个特征Foo,具体类型a和B都由特征Foo限定。我想返回一个向量

trait Foo { }

pub struct A {}
pub struct B {}

impl Foo for A {}
impl Foo for B {}


fn test() -> Vec<Foo> {
    let generic_vec: Vec<Foo> = Vec::new();
    generic_vec.push(A {});
    generic_vec.push(B {});
    return generic_vec;
}

目前的编译器正在抛出未为Foo实现大小trait的错误。我可以将Foo包装在一个Box中,但我不想返回trait对象的Vec,因为它们会带来运行时开销。

我想知道是否有一些Rust泛型特性允许我返回泛型类型的Vec,而不必使用trait对象。


共有2个答案

颛孙轩昂
2023-03-14

这里的问题是,不能保证仅仅因为<code>A</code>和<code>B</code>都实现了<code>Foo</code>它们将具有相同的大小。由于Rust的<code>Vec</code>是同质的,我们需要静态地保证其中的所有元素都有大小。

因此,解决方案是将绑定到trait的类型装箱。

trait Foo { }

pub struct A {}
pub struct B {}

impl Foo for A {}
impl Foo for B {}

type FooT = Box<dyn Foo>;

fn test() -> Vec<FooT> {
    let mut generic_vec: Vec<FooT> = Vec::new();
    generic_vec.push(Box::new(A {}));
    generic_vec.push(Box::new(B {}));
    return generic_vec;
}

现在,这些类型可能没有相同的大小,但指针(Box)将具有相同的大小,因此我们完全避免了这个问题,尽管需要付出一些代价,因为我们必须取消引用才能访问元素。

请注意,在这里我定义了类型别名FooT只是为了可读性,但当然,你可以只使用Box。

常永怡
2023-03-14

向量是内存中密集排列的数组,它要求其所有元素占用相同的空间量。元素的大小需要在编译时已知。Trait对象没有已知的大小,因此您不能将它们存储在Vec中。

如果要存储aB,最好的选择是使用枚举:

pub struct A;
pub struct B;

enum Either {
    A(A),
    B(B),
}

fn main() {
    let mut v = vec![];
    v.push(Either::A(A));
    v.push(Either::B(B));
}

枚举<code>或<code>的大小等于<code>a</code>和<code>B</code>大小中的最大值,可能还有一个空间用于表示当前变量是什么。这个大小在编译时是已知的,因此<code>或者<code>可以在向量中使用。

如果<code>A</code>和<code>B</code>实现了一个公共特性,并且您希望能够在向量的元素上调用该特性的方法,那么您也可以在<code>中的任一个</code>上实现该特性,方法是将所有方法调用转发到正确的变量。

 类似资料:
  • 介绍 针对 java.lang.reflect.Type 的工具类封装,最主要功能包括: 获取方法的参数和返回值类型(包括Type和Class) 获取泛型参数类型(包括对象的泛型参数或集合元素的泛型类型) 方法 首先我们定义一个类: public class TestClass { public List<String> getList(){ return new Arra

  • 我在覆盖接口中声明的方法时遇到了一些问题,该方法使用泛型参数作为其异常,并使用泛型作为其参数之一。为了说明,我编写了以下代码接口 通过javac运行,我得到 请注意,在接口中,metodoA和metodoB之间的唯一区别在于它们的参数。 为什么Implementadora(Implementadora)的metodoB(metodoB)(代码)不重写Interfaz(代码),但重写metodoB(

  • 我正在尝试用来自spring WebFlux的WebClient制作一个客户端库。 服务器返回如下JSON所示的响应: 结果字段包含元素数组,这些元素可以根据使用的API而不同。 有关该API的更多信息,请参阅ServiceNow产品中的表API。 正如您在文档中所看到的,API路径如下所示:GET/now/table/{tableName},其中tableName可以是不同的值,tipology

  • 如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。 背景: 我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如: 或

  • 在研究泛型时,我注意到泛型方法和泛型类型(类或接口)在类型引入语法上的一个差异使我感到困惑。 泛型方法的语法为 文件上说 为了彼此保持一致,我希望方法语法为 ,或者类型语法(for class)为,但事实显然并非如此。 为什么一个要介绍在前,另一个要介绍在后? 我主要以的形式使用泛型,并认为可能看起来很奇怪,但这是一个主观的参数,此外对于方法也是这样。您可以调用,类似于 在寻找技术解释时,我想在指

  • 我有一个问题,从抽象类中重写泛型方法。 这是我的抽象类: 当我创建类(B)来实现类(a)时,如下所示: 显示了(getData)方法中的以下编译错误: ”“B。getData“(“字符串函数(字符串)”不是“a”的有效重写。getData'('字符串函数(类型)‘)。dart(无效覆盖) 以及返回语句中的此错误: 类型为“String”的值不能从方法'getData'返回,因为它的返回类型为'St