generics - 无法创建多态类型,因为无法将特征制成对象

标签 generics rust

我有这个简化的 Rust 代码:

use std::io::Result;

pub trait PacketBuffer {}

pub trait DnsRecordData {
    fn write<T: PacketBuffer>(&self, buffer: &mut T) -> Result<usize>;
}

pub struct DnsRecord<R: DnsRecordData + ?Sized> {
    pub data: Box<R>,
}

pub struct DnsPacket {
    pub answers: Vec<DnsRecord<dyn DnsRecordData>>,
}

目的是 DnsRecord 应该能够保存任何实现 DnsRecordData 特性的结构,不同的结构代表 A、AAAA、CNAME 等。

失败并出现错误:

error[E0038]: the trait `DnsRecordData` cannot be made into an object
  --> src/lib.rs:14:5
   |
14 |     pub answers: Vec<DnsRecord<dyn DnsRecordData>>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DnsRecordData` cannot be made into an object
   |
   = note: method `write` has generic type parameters

最让我困惑的是,通过从 DnsRecordData::write() 中删除泛型,它编译得很好:

use std::io::Result;

pub trait PacketBuffer {}

pub trait DnsRecordData {
    fn write(&self, buffer: &mut dyn PacketBuffer) -> Result<usize>;
}

pub struct DnsRecord<R: DnsRecordData + ?Sized> {
    pub data: Box<R>,
}

pub struct DnsPacket {
    pub answers: Vec<DnsRecord<dyn DnsRecordData>>,
}

如果有人能解释我遗漏了什么,我将不胜感激。

最佳答案

该错误是由于您无法为 DnsRecordData 创建特征对象,因为该特征不是“对象安全的”。 trait objects section of The Rust Programming Language 中解释了这个概念。 .

在您的特定情况下,特征包含一个通用方法。要创建特征对象,编译器必须为特征合成一个 vtable,其中包含特征具有的每个方法的函数指针。但是因为 trait 有一个泛型方法,它实际上有尽可能多的方法可以被实例化,这可能是无限的。因此,您不能为 DnsRecordData 创建特征对象。

关于generics - 无法创建多态类型,因为无法将特征制成对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39412626/

相关文章:

rust - 我如何 "collapse"嵌套 `if let` 语句,它们都在其 `else` 子句中运行相同的代码?

rust - 如何在循环中更新可变引用?

rust - 如何使用 `index_mut` 获取可变引用?

linux - rust mio 甚至在标准输入上也总是报告

rust - 如何防止 Cargo 自动尝试下载较新版本的编译器?

java - Java 中的通用 vector

c# - 实体泛型 dbSet 获取数据表

java - Java 编译器是否有非类型删除的泛型扩展可用作第 3 方编译器扩展?

dictionary - 如何编写一个函数来处理通用映射及其条目类型?

java - 无法为嵌套类型推断类型变量 T