如何在嵌套的Rust类型中抽象泛型?

时间:2016-12-02 10:23:00

标签: generics nested rust traits

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的特征界限不再有趣。通过语言设计,无法使用没有Disk的句柄创建Read + Seek + Write。通过这个例子非常简单,如果类型有多个具有特征的成员,则类型可能变得极其复杂。

我想要的是:

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

type ExDisk = FIXME;

struct Partition {
    disk: ExDisk,
}

struct File {
    partition: Partition,
}

1 个答案:

答案 0 :(得分:1)

  

如何在嵌套类型中抽象泛型?

Rust根据特征进行抽象;所以使用特征(不是类型)。

具体来说,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特征作为其所代表的特征总和的简写。这不会抽象磁盘,但肯定很方便。