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

How do you abstract generics in nested Rust types?

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 的 trait-bounds 是什么不再有趣。通过语言设计,不可能创建句柄没有 Read + Seek + WriteDisk。通过这个例子非常简单,如果类型有多个具有特征的成员,类型可能会变得非常复杂。

我想要的是:

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

type ExDisk = FIXME;

struct Partition {
    disk: ExDisk,
}

struct File {
    partition: Partition,
}

How do you abstract generics in nested types?

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 特征作为它所代表的特征总和的简写。这并没有抽象磁盘,但肯定很方便。