2016-09-14 2 views
7

形質の内部の関数を戻り値のタイプがimpl Traitであると定義することは可能ですか?私は、複数の構造体で実装可能な特性を作成して、すべての関数がそれぞれ固有のコードを記述することなくすべて同じ方法で使用できるオブジェクトを返すようにしたいと考えています。特性定義内のインプット形質の使用

#![feature(conservative_impl_trait)] 

trait A { 
    fn new() -> impl A; 
} 

はしかし、私は次のエラーを取得する:

impl Trait not allowed outside of function and inherent method return types

は、これは単なるルストimpl Traitの現在の実装の制限または私はそれが間違って使用していますか?

答えて

5

この形質が現在実装されている特定のタイプのみを返す必要がある場合は、Selfを探している可能性があります。形質を使用して実証し、充実した一例を

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

struct Person; 

impl A for Person { 
    fn new() -> Person { 
     Person 
    } 
} 

をまたは::

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

例えば、これは、コンパイルします

trait A { 
    fn new<S: Into<String>>(name: S) -> Self; 
    fn get_name(&self) -> String; 
} 

struct Person { 
    name: String 
} 

impl A for Person { 
    fn new<S: Into<String>>(name: S) -> Person { 
     Person { name: name.into() } 
    } 

    fn get_name(&self) -> String { 
     self.name.clone() 
    } 
} 

struct Pet { 
    name: String 
} 

impl A for Pet { 
    fn new<S: Into<String>>(name: S) -> Pet { 
     Pet { name: name.into() } 
    } 

    fn get_name(&self) -> String { 
     self.name.clone() 
    } 
} 

fn main() { 

    let person = Person::new("Simon"); 
    let pet = Pet::new("Buddy"); 

    println!("{}'s pets name is {}", get_name(&person), get_name(&pet)); 
} 

fn get_name<T: A>(a: &T) -> String { 
    a.get_name() 
} 

Playground

を注意点として..私はStringをここでは&strの参考にして使った。明示的な生涯の必要性と、潜在的には手元の問題への焦点の欠如。コンテンツを借用するときには&str参照を返すのが一般的にはコンベンションだと思うが、それはここでは適切だと思われる。しかし、実際の例をあまりにも邪魔したくない。

+0

hhh;可能であるかどうか分からなかった!どうもありがとうございました。 – Ameo

+1

大歓迎です! :) –

+2

これは 'impl Trait'を返すのと同じではありません。たとえば、 'Person'が' Pet'を返すメソッドを追加することはできませんが、 'Pet'は' Person'を返しますが、両方とも 'A'を実装します。 [RFC(1522)](https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md)にはこの制限が記載されており、最終的にそれを削除したいという願いが表明されています「初期制限」の最初の箇条書き)。 – trentcl

6

trentcl mentionsとして、impl Traitを現在の形質メソッドの戻り位置に配置することはできません。 RFC 1522から

impl Trait may only be written within the return type of a freestanding or inherent-impl function, not in trait definitions or any non-return type position. They may also not appear in the return type of closure traits or function pointers, unless these are themselves part of a legal return type.

  • Eventually, we will want to allow the feature to be used within traits [...]
+1

もう一度Shepmasterに感謝します。私はこれを完全に考慮していなかったので、私の答えは直接問題に対処していないことがわかります。それは今受け入れられ、OPを助けたようだ。ここからどのように進むのですか?おそらく 'impl Trait'の特定の使用を取り除くために質問を編集すべきか、それとも完全に回答を取り除くべきでしょうか? –

+2

@SimonWhitehead私は質問を非常に徹底的に編集するのは嫌です。私は両方の答えを残すことはいいと思います。 "あなたは* X *をやることはできませんが、ここには役立つ回避策があります"などのように答えを変えることができます。直接の質問に答え、有用な選択肢を提供することは価値ある貢献です。チェックマークは、主に「この回答がOPを最も助けました」という意味です。投票は「この回答は私を助けました」という意味です。 – Shepmaster

+0

問題ありません。助けてくれてありがとう! –

1

あなたも、それが明示的に戻り値の型に名前を付けることで、「自己」を返していない場合には類似した何かを得ることができます。

trait B {} 
struct C; 

impl B for C {} 

trait A { 
    type FReturn: B; 
    fn f() -> Self::FReturn; 
} 

struct Person; 

impl A for Person { 
    type FReturn = C; 
    fn f() -> C { 
     C 
    } 
} 
関連する問題