Qual è la differenza tra "impl <T> tratto per T dove T: tratto2" e "impl Trait per dyn Trait2"?

Oct 28 2020

Quando si estendono i tratti definiti in altre casse, sembrano esserci due modi per implementare di default un nuovo tratto.

La definizione originale di un tratto è

pub trait Trait1 {
    fn f1(&self);
}

Al fine di estendere la funzionalità di questo tratto, definiamo un tratto Trait2,

pub trait Trait2 {
    fn f2(&self);
}

Ora, poiché vogliamo che la funzionalità sia disponibile per impostazione predefinita, possiamo implementare quanto segue

impl<T> Trait2 for T
where
    T: Trait1,
{
    pub fn f2(&self) {
        self.f1()
    }
}

impl Trait2 for dyn Trait1 {
    pub fn f2(&self) {
        self.f1()
    }
}

Quello che ho osservato è che, quando si mescolano con oggetti tratto, sono necessarie entrambe queste implementazioni.

Capisco che impl<T>quello è per le classi concrete mentre l'altro è per gli dynoggetti. È corretto? C'è un modo per condividere qui l'implementazione predefinita per entrambi questi tipi? Nel mio scenario, ho dovuto copiare e incollare l'intera implementazione con solo la modifica della prima riga.

Risposte

3 EvilTak Oct 28 2020 at 06:51

Se ho capito correttamente la tua domanda, aggiungi semplicemente il limite non dimensionato ( ?Sized) a T:

impl<T> Trait2 for T where T: Trait1 + ?Sized

Questo implementa Trait2anche i tipi non dimensionati (ad es. dyn Trait1) Che implementano Trait1. Per impostazione predefinita, tutti i parametri di tipo sono dimensionati e quindi non corrispondono a tipi non dimensionati.

Terreno di gioco