2016-12-02 18 views
1
struct Disk<T: Read + Seek + Write> { 
    handle: T, 
} 

struct Partition<T: Read + Seek + Write> { 
    disk: Disk<T>, 
} 

struct File<T: Read + Seek + Write> { 
    partition: Partition<T>, 
} 

struct Partitionの時点では、もはや何がDiskの特性境界であるか興味深いものではない。言語設計によって、を持たないハンドルを持つを作成することはできません。この例は非常に単純ですが、型が複数のメンバーを持つ場合、型が非常に複雑になる可能性があります。私が欲しいものネストされたRustタイプでジェネリックスを抽象化するにはどうすればよいですか?

は次のとおりです。

struct Disk<T: Read + Seek + Write> { 
    handle: T, 
} 

type ExDisk = FIXME; 

struct Partition { 
    disk: ExDisk, 
} 

struct File { 
    partition: Partition, 
} 

答えて

1

どのようにネストされたタイプで、あなた抽象ジェネリック?

錆は特色によって抽象化を行う。そのため、特性(型ではない)を使用してください。

具体的には、Partitionは、Disk<T: ...>ではなく、特性を実装する一般的なパラメータに依存する必要があります。

trait Volume {} 

struct Disk<T: Read + Seek + Write> { 
    handle: T, 
} 

impl<T: Read + Seek + Write> Volume for Disk<T> {} 

struct Partition<V: Volume> { 
    volume: V, 
} 

struct File<V: Volume> { 
    partition: Partition<V>, 
} 

またFile自体は抽象パーティションに依存性があります。

このVolume特性を使用すると、ジェネリックパラメータを完全に削除することもできます。限りVolume形質は、オブジェクト安全であるように、オブジェクトが背景にあるローカル参照を格納する必要はありません

struct Partition { 
    volume: Box<Volume>, 
} 

struct File { 
    partition: Partition, 
} 

それはオーバーヘッドのほんの少し(動的割り当て+間接呼び出し)を追加し、家族の代わりにあなたに単一のタイプを与えます。


だけ冗長性を軽減するための別の解決策は、特にこの目的のために新しいtraitを導入することである。

trait Volume: Read + Seek + Write {} 

impl<T> Volume for T where T: Read + Seek + Write {} 

は、あなたが、その後、特徴、それの合計のための短い手としてVolume形質を使用することができますを表す。これはディスクを抽象化しませんが、確かに便利です。

+0

私はこれがどのように質問に答えるかはわかりません(ただし、OPがそれを受け入れたようにはっきりしていますが)。 OPは 'struct Partition {'と言うことができるようにしたいと思っていましたが、この答えにはまだ 'Partition'と' File'のジェネリックパラメータがあります。 – Shepmaster

+1

@Shepmaster:私は複雑さを減らす(そして内側のメンバーの境界を抽象化する)という質問を読んだが、必ずしもすべての境界を取り除くわけではない。 'Volume'がオブジェクトセーフであれば、' Partition'に 'Box 'を含めることが可能であり、それはパラメータなしであることに注意してください。 –

+0

これは複雑さを軽減するので、私はこれを受け入れました。箱 'Box 'の特性オブジェクトを使用すると、質問にもっと正確に答えることができます。 – eddy

関連する問題