Generics 无法创建多态类型,因为无法将特征生成对象
我有一个简化的防锈代码:Generics 无法创建多态类型,因为无法将特征生成对象,generics,rust,Generics,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 d
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>>,
}
让我最困惑的是,通过从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>>,
}
使用std::io::Result;
发布特性包缓冲区{}
发布特征DnsRecordData{
fn write(&self,buffer:&mut dyn PacketBuffer)->结果;
}
发布结构DnsRecord{
发布数据:框,
}
发布结构DnsPacket{
酒吧回答:Vec,
}
如果有人能解释我遗漏了什么,我将不胜感激。错误源于这样一个事实,即您无法为
DnsRecordData
创建trait对象,因为trait不是“对象安全的”。这一概念在本手册中有解释
在您的特定情况下,trait包含一个通用方法。要创建trait对象,编译器必须为trait合成一个vtable,其中包含trait拥有的每个方法的函数指针。但是由于trait有一个泛型方法,因此它实际上拥有尽可能多的方法,因为该方法可以被实例化,这可能是无限的。因此,不能为DnsRecordData
创建特征对象
其目的是DnsRecord
应该能够保存实现DnsRecordData
特性的任何结构
代码上不是这么说的
Vec<DnsRecord<dyn DnsRecordData>>
特质是可以实现的,但它们也有自己的类型。为了创建这种类型,trait需要是对象安全的-
正如错误消息所述,此trait不能是trait对象,因为该方法上存在泛型类型
第一个错误指出,DnsRecordData
要求参数化它的任何类型都必须实现DnsRecordData
。但是,trait对象的类型实际上并没有实现这一点。通常,您会通过引用(&dyn DnsRecordData
)或框(box
)使用trait对象,这两者都应该实现trait,以防止出现此错误
pub struct DnsPacket<D>
where
D: DnsRecordData,
{
pub answers: Vec<DnsRecord<D>>,
}