generics rust traits dynamic-dispatch trait-objects

generics - El rasgo no puede convertirse en un objeto



rust traits (3)

Tengo el siguiente código:

extern crate futures; // 0.1.24 use futures::Future; use std::io; struct Context; pub trait MyTrait { fn receive(context: Context) -> Future<Item = (), Error = io::Error>; } pub struct MyStruct { my_trait: MyTrait, }

Cuando intento compilarlo, aparece el mensaje de error:

error[E0038]: the trait `MyTrait` cannot be made into an object --> src/lib.rs:13:5 | 13 | my_trait: MyTrait, | ^^^^^^^^^^^^^^^^^ the trait `MyTrait` cannot be made into an object | = note: method `receive` has no receiver

Creo que sé por qué sucede, pero ¿cómo me refiero al rasgo de la estructura? ¿Es posible? ¿Quizás hay otras formas de implementar el mismo comportamiento?


Hay una cuarta opción disponible, pero esto hará que su estructura no sea de tamaño, es decir, no podrá crear instancias de esta estructura.

pub trait MyTrait {} pub struct MyStruct { my_trait: dyn MyTrait + ''static, }

Esto significa que MyStruct es un tipo sin tamaño y no puede crear instancias directas de ese tipo. Como Rust actualmente no tiene una forma de asignar estructuras directamente en la pila, no sé si puede crear una instancia de ese tipo. Pero bueno, se compila .


Puede agregar un parámetro de tipo a su estructura, como en la respuesta de Zernike , o usar un objeto de rasgo.

Usar el parámetro type es mejor para el rendimiento porque cada valor de T creará una copia especializada de la estructura, lo que permite el envío estático. Un objeto de rasgo utiliza la distribución dinámica, por lo que le permite intercambiar el tipo concreto en tiempo de ejecución.

El enfoque del objeto rasgo se ve así:

pub struct MyStruct<''a> { my_trait: &''a dyn MyTrait, }

O esto:

pub struct MyStruct { my_trait: Box<dyn MyTrait>, }

Sin embargo, en su caso, MyStruct no se puede convertir en un objeto porque receive es un método estático. Tendría que cambiarlo para tomar &self o &mut self como su primer argumento para que esto funcione. También hay otras restricciones .