2016-06-30 12 views
0

Javaでは、オブジェクト(厳密なインスタンス)のコレクション(ベクトル)を作成しようとしていますが、それぞれがインタフェース(特性)を実装していますコレクションの上にすべてのメソッドを呼び出します。Rustで形質を実装するオブジェクトのベクトルを作成する

私はそれよりも簡単に回答を得ることができるすべての部分が含まれている1つのサンプルファイルに減らしました。

特定の例では、メッセージを表示して失敗することを
// main.rs - try and compile using just "rustc main.rs" 
use std::io::Result; 

/// ////// Part 1 
// Types used by implementors of the trait, and in creating a vector of implementors of the trai 
pub struct SampleResult { 
    metric: String, 
} 

pub trait SampleRunner { 
    fn run(&self, &'static str) -> Result<SampleResult>; 
} 

pub struct Sample { 
    name: &'static str, 
    runner: &'static SampleRunner, 
} 

/// /////// Part 2 
/// Create one specific static instance of such as Sample 
static SAMPLE1: Sample = Sample { 
    name: "sample", 
    runner: &Sample1, 
}; 

// need a struct to hold the run method to satisfy the trait??? 
struct Sample1; 

// Implement the trait for this specific struct 
impl SampleRunner for Sample1 { 
    fn run(&self, name: &'static str) -> Result<SampleResult> { 
     println!("Name: {}", name); 
     Ok(SampleResult { metric: "OK".to_string() }) 
    } 
} 

/// /////// Part 3 
/// Using the existing static instances of Sample struct, by creating a vector of references for them 
/// then iterating over the vector and calling the trait method on each one 
fn main() { 
    let sample_set: Vec<&Sample> = vec![&SAMPLE1]; 

    for sample in sample_set.iter() { 
     match sample.runner.run(sample.name) { 
      Ok(result) => println!("Success"), 
      _ => panic!("failed"), 
     } 
    } 
} 

error[E0277]: the trait bound `SampleRunner + 'static: std::marker::Sync` is not satisfied in `Sample` 
    --> <anon>:21:1 
    | 
21 | static SAMPLE1: Sample = Sample { 
    | _^ starting here... 
22 | |  name: "sample", 
23 | |  runner: &Sample1, 
24 | | }; 
    | |__^ ...ending here: within `Sample`, the trait `std::marker::Sync` is not implemented for `SampleRunner + 'static` 
    | 
    = note: `SampleRunner + 'static` cannot be shared between threads safely 
    = note: required because it appears within the type `&'static SampleRunner + 'static` 
    = note: required because it appears within the type `Sample` 
    = note: shared static variables must have a type that implements `Sync` 

しかし、私はSyncに関連し、私が取ったアプローチに応じて、さまざまな問題を抱えている、Sized、などなど

+0

:(特にタイトル)この質問は非常に関連している[この質問](http://stackoverflow.com/questions/25818082/vector-of-objects-belonging-to- a-trait)。 –

答えて

1

コードには2つの小さなエラーがあります。最初はエラーで記述されていますが、静的な値は同期特性を実装していないため安全ではないことがわかります。静的な値が複数のスレッドから操作される場合に備えて準備をしようとします。ここで、最良の解決策は単に値をconstとマークすることです。その後、メインに&SAMPLE1の生存期間に問題があり、「letキーワードを使用して寿命を延ばす」という方法で解決できます。

これらの小さな変更後のコードはコンパイルし、次のようになります。

use std::io::{Result}; 

pub struct SampleResult { 
    metric: String 
} 

pub trait SampleRunner { 
    fn run(&self, &'static str) -> Result<SampleResult>; 
} 

pub struct Sample { 
    name: &'static str, 
    runner: &'static SampleRunner 
} 

// Make it const 
const SAMPLE1: Sample = Sample { name: "sample", runner: &Sample1 }; 

struct Sample1; 

impl SampleRunner for Sample1 { 
    fn run(&self, name: &'static str) -> Result<SampleResult> { 
     println!("Name: {}", name); 
     Ok(SampleResult {metric: "OK".to_string() }) 
    } 
} 

fn main() { 
    // Extend the lifetime of the borrow by assigning it to a scope variable 
    let borrowed_sample1 : &Sample = &SAMPLE1; 
    let sample_set: Vec<&Sample> = vec!(borrowed_sample1); 

    for sample in sample_set.iter() { 
     match sample.runner.run(sample.name) { 
     Ok(result) => println!("Success"), 
     _ => panic!("failed") 
     } 
    } 
} 

はしかし、私はあなたがSampleRunnerのすべての実装のための新しい構造体を作成するために持っているとして、あなたがコードに満足していないことがわかります。ラムダ関数を使用する別の方法があります(Rustドキュメントは単にそれらをClosuresと呼んでいます)。将来の訪問者のための

use std::io::{Result}; 

pub struct SampleResult { 
    metric: String 
} 

type SampleRunner = Fn(&'static str) -> Result<SampleResult>; 

pub struct Sample { 
    name: &'static str, 
    runner: &'static SampleRunner 
} 

// Still const, use a lambda as runner  
const SAMPLE1: Sample = Sample { name: "sample", runner: &|name| { 
    println!("Name: {}", name); 
    Ok(SampleResult {metric: "OK".to_string() }) 
} }; 

fn main() { 
    let borrowed_sample1 : &Sample = &SAMPLE1; 
    let sample_set: Vec<&Sample> = vec!(borrowed_sample1); 

    for sample in sample_set.iter() { 
     // Must parenthese sample.runner so rust knows its a field not a method 
     match (sample.runner)(sample.name) { 
     Ok(result) => println!("Success"), 
     _ => panic!("failed") 
     } 
    } 
} 
+0

ありがとう!私は、エラーメッセージ、または私が読んだことのあるすべての本/読んでいることから、これまでに得たことはないと思う。私は静的なものとconstのものについて少し漠然としていることがわかりました。そして、私はそのような初期化された構造のためにconstを使用することは考えていませんでした....すべての例が非プリミティブ(i32など) )。 –

+0

「SampleRunner + 'static」をスレッド間で共有できるようにするためのアイデアはありますか?注: 'SampleRunner + 'static'はスレッド間で安全に共有できません。どのようにそれに "同期"を実装するには? –

+0

@AndrewMackenzie参照['RefCell'](https://doc.rust-lang.org/std/cell/struct.RefCell.html) –

関連する問題