2015-07-23 1 views
0

Извините, если это кажется тривиальным, но я пытаюсь выполнить простую операцию, но мне очень трудно это сделать. Я просто хочу иметь два объекта признаков, в которых есть вектор, содержащий кучу другого объекта.Охватывая объекты признаков в объекте базовой цели

trait MetaClass { 
    fn new() -> Self; 
    fn add(&self, subtrait: Box<SubClass>); 
} 

struct MetaStruct { 
    elems: Vec<Box<SubClass>>, 
} 

impl MetaClass for MetaStruct{ 
    fn new() -> MetaStruct { 
     MetaStruct{ 
      elems: Vec::new(), 
     } 
    } 

    fn add(&self, subtrait: Box<SubClass>){ 
     // if I reformulate the above to 'fn add(&self, subtrait: SubClass){' 
     // and use the below I get the trait `core::marker::Sized` is not implemented for the type `SubClass` 
     //self.elems.push(Box::new(subtrait)); 
     self.elems.push(subtrait); 
    } 
} 


trait SubClass{ 
    fn new() -> Self; 
} 

struct MySubClass { 
    data: i32, 
} 

impl SubClass for MySubClass { 
    fn new() -> MySubClass{ 
     MySubClass{ 
      data: 10, 
     } 
    } 
} 


fn main(){ 
    let mut meta = Box::new(MetaStruct::new()); 
    // ideally I just want to do meta.add(MySubClass::new()) but as mentioned above that has some sizing issues :'(
    meta.add(Box::new(MySubClass::new())); 
} 

Ошибка я получаю:

<anon>:45:11: 45:38 error: cannot convert to a trait object because trait `SubClass` is not object-safe [E0038] 
<anon>:45 meta.add(Box::new(MySubClass::new())); 
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Вот ссылка на ржавчину игры: http://is.gd/pjLheJ

Я также попытался следующие, но получил ту же ошибку:

meta.add(Box::new(MySubClass::new()) as Box<SubClass>); 

В идеале, если есть способ сделать это с помощью статической отправки Rust, которая была бы идеальной, но Я был бы в порядке с динамической диспетчеризацией. В каждом случае, я думаю, будет иметь смысл, чтобы MetaClass фактически принадлежал объекту подкласса, поэтому я не хочу передавать ссылку на него, но весь объект сам.

+0

Это было [перекресток, отправленный в Reddit] (http://www.reddit.com/r/rust/comments/3ebxuy/trouble_understanding_cascading_trait_objects/) – Shepmaster

ответ

1

I just want to have two trait objects whereby one has a Vector that contains a bunch of the other object.

Этого достаточно прямолинейно:

trait TraitOne { 
    fn add(&mut self, another: Box<TraitTwo>); 
} 

trait TraitTwo { 
    fn value(&self) -> u8; 
} 

struct Container(Vec<Box<TraitTwo>>); 
impl TraitOne for Container { 
    fn add(&mut self, another: Box<TraitTwo>) { 
     self.0.push(another); 
    } 
} 

struct ThingOne(u8); 
impl TraitTwo for ThingOne { 
    fn value(&self) -> u8 { self.0 } 
} 

struct ThingTwo(u8, u8); 
impl TraitTwo for ThingTwo { 
    fn value(&self) -> u8 { self.0 + self.1 } 
} 

fn main() { 
    let mut trait_1: Box<TraitOne> = Box::new(Container(vec![])); 

    let thing_1: Box<TraitTwo> = Box::new(ThingOne(42)); 
    let thing_2: Box<TraitTwo> = Box::new(ThingTwo(21, 21)); 

    trait_1.add(thing_1); 
    trait_1.add(thing_2); 
} 

Настоящее ошибка о безопасности объекта. Хуон Уилсон (член основной группы Rust) написал great blog post about this.

В вашем случае у вас есть эта черта:

trait SubClass{ 
    fn new() -> Self; 
} 

Это не является объектом безопасным, цитируя Юон (курсив мой):

There’s two fundamental ways in which this can happen, as an argument or as a return value, in either case a reference to the Self type means that it must match the type of the self value, the true type of which is unknown at compile time.

То есть, как должны быть распределены на много байт стек или кучу, чтобы удерживать объект, возвращенный fn new() -> Self? Вы не можете знать, потому что у вас есть только объект с чертами.

Одно решение, чтобы убедиться, что Self в вашей черты Sized, согласно followup blog post:

trait SubClass { 
    fn new() -> Self where Self: Sized; 
} 

Тогда просто исправить некоторые Изменчивость несовпадений в вашей черты, и он компилирует.

+0

Gah, не понимал, что это было легко реализовать. Эта простая вещь исправила мою проблему! Еще раз спасибо! – bge0

Смежные вопросы