繁体   English   中英

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

[英]Unable to create a polymorphic type because the trait cannot be made into an object

我有这个简化的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<DnsRecordData>>,
}

fn main() {}

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

这失败并出现错误:

error: the trait bound `DnsRecordData + 'static: DnsRecordData` is not satisfied [--explain E0277]
  --> src/main.rs:14:5
   |>
14 |>     pub answers: Vec<DnsRecord<DnsRecordData>>,
   |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by `DnsRecord`

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

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

use std::io::Result;

pub trait PacketBuffer {}

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

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

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

fn main() {}

如果有人能解释我所缺少的东西,我会非常感激。

目的是DnsRecord应该能够保存任何实现DnsRecordData特征的结构

这不是代码所说的。

Vec<DnsRecord<DnsRecordData>>

这是包含特征 DnsRecordData的struct DnsRecord的向量。 如果你想要“任何实现DnsRecordData特征的结构”,你需要一个通用:

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

特征可以实现 ,但它们也有自己的类型。 为了创建这种类型,特征需要是对象安全的 - 特征对象不是对象安全的错误

正如错误消息所述,此特征不能是特征对象,因为该方法上存在泛型类型。

第一个错误表明DnsRecord要求参数化的任何类型都必须实现DnsRecordData 但是,特征对象的类型实际上并没有实现。 通常,您通过引用( &DnsRecordData )或框( Box<DnsRecordData> )使用特征对象,两者都应实现特征,以防止此错误。

第二个错误来自于您无法为DnsRecordData创建特征对象,因为特征不是“对象安全”。 Rust编程语言特征对象部分解释了这个概念。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM