2016-12-04 14 views
0

私はプレーンな形質Fruitと拡張型形質WeightedFruitを持っています。 Rustコンパイラは、のFruit特性を受け取りますが、はBTreeSetではありません。ソートされたセットを作るために何を変更する必要がありますか?コレクションの拡張型形質

pub trait Fruit { } 

pub trait WeightedFruit: Fruit + Ord { } 

pub fn main() { 
    let unsorted: LinkedList<Box<Fruit>> = LinkedList::new(); 
    let sorted: BTreeSet<Box<WeightedFruit>> = BTreeSet::new(); 
} 

エラーメッセージは以下のとおりです。

the trait `WeightedFruit` cannot be made into an object 
trait `WeightedFruit: std::cmp::Ord` not satisfied 
... 
+4

同じ種類の具体的なオブジェクトだけを比較することができるので(実際には 'Apple'sと' Orange'sを比較することはできません。 1つの容器に複数の異なるフルーツを保管する必要がありますか?私はBox (とEq)のために 'impl Ord 'を試してみたいと思いますが、今は時間がありません。明日まだ開いているなら、私は遊びに行くでしょう。 –

+0

これは、同じエラーメッセージ(「特性...オブジェクトにすることはできません」)を持つ他の既存の質問とどのように違いますか? – Shepmaster

+0

私は本当にいくつかのケースではオブジェクトとしての特性を使用できるように思われる既存の質問を見つけることができませんでした(上記のLinkedlistの部分をコンパイルします)。そして、ええ、私の意図は、リンゴとオレンジを比較することでした... :-) OO言語はそれに何ら問題はありません。 – zaari

答えて

1
pub trait WeightedFruit: Fruit + Ord { } 

これはWeightedFruitを実装し、すべての構造体は、それ自体に匹敵する必要がありますと言います。しかし、その特性を実装する他の構造体には向かない。したがって、AppleWeightedFruitを実装する場合、がWeightedFruitを実装する場合、それはOrangeに匹敵しますが、お互いには匹敵するものではなく、Appleに匹敵します。

「WeightedFruit」のコレクションは交換できないため、コレクションは作成できません。リンゴとオレンジは、それぞれ異なる種類に匹敵するため、異なるものです。

代わりに、あなたがこのような何かをしたい:

use std::cmp::*; 
use std::collections::*; 

pub trait Fruit { } 

pub trait WeightedFruit: Fruit { 
    fn weight(&self) -> u32; 
} 

impl Ord for WeightedFruit { 
    fn cmp(&self, other: &Self) -> Ordering { 
     self.weight().cmp(&other.weight()) 
    } 
} 

impl PartialOrd for WeightedFruit { 
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 
     Some(self.cmp(other)) 
    } 
} 

impl PartialEq for WeightedFruit { 
    fn eq(&self, other: &Self) -> bool { 
     self.weight() == other.weight() 
    } 
} 

impl Eq for WeightedFruit {} 


struct Apple { 
    weight: u32 
} 

impl Fruit for Apple {} 

impl WeightedFruit for Apple { 
    fn weight(&self) -> u32 { 
     self.weight 
    } 
} 

struct Orange { 
    weight: u32 
} 

impl Fruit for Orange {} 

impl WeightedFruit for Orange { 
    fn weight(&self) -> u32 { 
     self.weight 
    } 
} 

pub fn main() { 
    let unsorted: LinkedList<Box<Fruit>> = LinkedList::new(); 
    let sorted: BTreeSet<Box<WeightedFruit>> = BTreeSet::new(); 
} 

これは、すべてのWeightedFruit果実がそのweight、すべてWeightedFruitこのweightを使用して、他のWeightedFruitと比較することができますを提供することができなければならないと述べています。今度は特性オブジェクトをWeightedFruitにして置き換えることができます。


Ordthe trait ... cannot be made into an objectエラーについての補足説明:あなたは、形質オブジェクトを操作する場合

、特徴は、オブジェクト指向言語でのインターフェイスのようにちょっと見えます。あなたはそれを実装する複数の構造と、特質オブジェクトを取る関数を持つことができます。それは、オブジェクト上の特性の関数を呼び出すことができます。なぜなら、それはオブジェクトを持つことを知っており、すべてのオブジェクトに対してまったく同じであるからです。ちょうどOO言語のように。

ただし、特性には1つの特別な機能があります。関数宣言でSelf型を使用できます。 Selfは常にその特性を実装する型です。形質のいずれかにSelfを使用する形質は特別なものになり、もはや特質オブジェクトとして使用することができなくなります。 structがそのような特性を実装するたびに、それは異なるバージョン(Selfが異なるバージョン)を実装しています。それを実装するすべての構造体が異なるバージョンを実装しているため、特性オブジェクトを作成することはできません。

Ordは、JavaのComparable<T>のようになります。Tがコンパイラによって選択されています。そして、あなたが何かを受け入れるメソッドをJavaの中で受け入れることができないのと同じように、Ord traitオブジェクトを受け入れるメソッドを持つことはできません。

+1

私はRustのドキュメントにこのような例と情報があることを望みます。これはまさに私がやろうとしたことです。ありがとうございました! – zaari

関連する問題