2017-10-23 3 views
0

これは現在直面している問題の簡略化されたバージョンです。 オブジェクトプールからの借用時の静的な寿命の回避

trait SuperObject { 
    fn object_name(&self) -> String; 
} 

trait Inspect { 
    fn inspect(&self); 
} 

impl Inspect for SuperObject { 
    fn inspect(&self) { 
     println!("I am a Superobject."); 
    } 
} 

struct Object { 
    name: String 
} 

impl SuperObject for Box<Object> { 
    fn object_name(&self) -> String { 
     format!("I am {}.", self.name.clone()) 
    } 
} 

struct ObjectPool { 
    object1: Box<Object>, 
    object2: Box<Object>, 
    object3: Box<Object> 
} 

impl ObjectPool { 
    pub fn new() -> ObjectPool { 
     ObjectPool { 
      object1: Box::new(Object { name: String::from("Object 1") }), 
      object2: Box::new(Object { name: String::from("Object 2") }), 
      object3: Box::new(Object { name: String::from("Object 3") }) 
     } 
    } 
    fn all_objects(&self) -> Vec<&SuperObject> { 
     let mut ret: Vec<&SuperObject> = Vec::new(); 
     ret.push(&self.object1); 
     ret.push(&self.object2); 
     ret.push(&self.object3); 
     ret 
    } 
} 

fn main() { 
    let objectpool: ObjectPool = ObjectPool::new(); 
    let allobjects: Vec<&SuperObject> = objectpool.all_objects(); 
    for i in &allobjects { 
     println!("{}", i.object_name()); 
     // Comment the following line in order to drop error E0597 
     i.inspect(); // FIXME: borrowed value must be valid for the static lifetime 
    } 
} 

次のようにこのスニペットをコンパイルしようとするとエラーがある:私が理解デフォルトの静的寿命を持っているhttps://doc.rust-lang.org/book/second-edition/ch19-02-advanced-lifetimes.html

でいう、オブジェクトが、インスタンス化されることから、多くの検索後

error[E0597]: `objectpool` does not live long enough 
    --> src/main.rs:50:41 
    | 
50 |  let allobjects: Vec<&SuperObject> = objectpool.all_objects(); 
    |           ^^^^^^^^^^ does not live long enough 
... 
56 | } 
    | - borrowed value only lives until here 
    | 
    = note: borrowed value must be valid for the static lifetime... 

error: aborting due to previous error 

を、

ObjectPoolのall_objectsメソッドの出力は、スニペットをデバッグしようとしたときに発生するエラーの1つとして示されているように、コンパイラによって静的であると考えられます。

これは、オブジェクトプールを完全に廃棄することを伴わないアクションの最良の方法は何ですか?または、錆の実装に適したよりエレガントな抽象化がありますか?

答えて

3

問題はimpl Inspect for SuperObjectです。別の形質の形質を実装すると、ではなく、があなたの期待通りのものになります。基本的にルールは決してありません。基本的には、&(SuperObject + 'static)がある場合にのみ、Inspectとして扱うことができます。あなたが欲しいのは

impl<T: SuperObject + ?Sized> Inspect for T { 
    fn inspect(&self) { 
     println!("I am a Superobject."); 
    } 
} 
+0

です。さて、ジェネリックスをブラッシュアップする必要があります。上記の解決策では、Inspectの実装は現在、SuperObjectに対してのみ許可されています。例えば、SuperObject以外の構造体(例えば、OtherSuperObject)に対してInspectを使用しようとすると、実現できません。そうですか?この場合、回避策はありますか? –

+0

それは問題です。私はそれをどのように修正するか分からない。しかし、通常私はそのような状況では、私はRustの多形性のデザインを強制しようとしていると錆びた方法でデザインを再加工した後にすべてを稼働させることに気づいた –