2016-11-22 5 views
0

私は動的に錆構造体の中に、データベースの結果をマッピングするためEntityインタフェースを作るしようとしています:使用形質は

error: no method named map found for type T in the current scope
ret.push(query.entity.map(row.unwrap())); |
note: the method map exists but the following trait bounds were not satisfied: T : std::iter::Iterator = help: items from traits can only be used if the trait is implemented and in scope; the following traits define an item map , perhaps you need to implement one of them: = help: candidate #1: models::holders::database::Entity = help: candidate #2: std::iter::Iterator

+1

あなたの例は、最小の例としてはそれほど立派なものではありませんが、 'DbQuery'や' DbMapper ::/DbMapper :: 'に' Entity'を実装するために 'T'を制約していないと答えました。発見する。 –

+0

申し訳ありませんが、私はそれを説明するために最小限のコードを使用しました。 残念ながら私は既にTの代わりにEntityを試しましたが、同じエラーが表示されます – plailopo

+1

こんにちは - これはやや小さめですが、play.rust-lang.orgに入れてコンパイルして同じエラーが発生するほど十分ではありませんが、だから確かめるのはちょっと難しい。 –

答えて

2

Here is a version of your code that runs on the playground

pub trait Entity { 
    fn map(&self, Result<QueryResult>) -> Self; 
} 

pub struct DbQuery<T> { 
    pub sql: String, 
    pub params: Vec<Value>, 
    pub limit: i32, 
    pub paged: Option<Pagination>, 
    pub entity: T, 
} 

pub struct Settings { 
    pub name: String, 
    pub value: Option<String>, 
} 

impl Entity for Settings { 
    fn map(&self, result: Result<QueryResult>) -> Settings { 
     // ... 
     Settings { 
      name: "hello".to_string(), 
      value: None, 
     } 
    } 
} 

impl DbMapper { 
    // ... 

    pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> { 
     println!("query find SQL: {}", query.sql); 
     let mut stmt = &self.pool.prepare(query.sql).unwrap(); 
     let ret = Vec::new(); 
     for row in stmt.execute(query.params).unwrap() { 
      ret.push(query.entity.map(row.unwrap())); 

     } 

     Some(ret) 
    } 
} 

しかし、私はエラーを取得します問題を再現します:

pub struct QueryResult; 
pub struct Value; 
pub struct Pagination; 
pub struct DbMapper; 

pub trait Entity { 
    fn map(&self, Result<QueryResult,()>) -> Self; 
} 

pub struct DbQuery<T> { 
    pub sql: String, 
    pub params: Vec<Value>, 
    pub limit: i32, 
    pub paged: Option<Pagination>, 
    pub entity: T, 
} 

pub struct Settings { 
    pub name: String, 
    pub value: Option<String>, 
} 

impl Entity for Settings { 
    fn map(&self, result: Result<QueryResult,()>) -> Settings { 
     // ... 
     Settings { 
      name: "hello".to_string(), 
      value: None, 
     } 
    } 
} 

impl DbMapper { 
    // ... 

    pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> { 
     println!("query find SQL: {}", query.sql); 

     // ########## attempt to call map() 
     let _ = query.entity.map(Ok(QueryResult {})); 

     let ret = Vec::new(); 
     Some(ret) 

    } 
} 

fn main() {} 

問題はですfindメソッドのDbQuery<T>引数のは、TEntityタイプであるという考えを持っていません。だから私たちはそれを伝える必要があります:

pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> 
    where T: Entity 
{ 
    // ... code here ... 
} 

This now compiles and runs

コンパイラは、Tが何らかの説明のEntityであることを知り、その上でmapメソッドを呼び出すことができます。

+0

うん!!!ありがとう。私はRustの新しいバイです。 しかしTの代わりにEntityで作業してみませんか? – plailopo

+0

あなたが明示的にそれを与えるまで、 'T'はそのメソッドにコンテキストを持たないからです。コンパイラの観点から、あなたは「ここにはT型があります...それはどんな型でもよい」と言っています。コンパイラは、型がmapメソッドを実装していることを知ることはできません。エンティティ型であることを示すヒントを与えることによって、コンパイラはマップを呼び出すことができることを認識します。 –

関連する問題