簡體   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