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

标签 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的特征边界是什么已经不再有趣了。通过语言设计,不可能创建一个没有Read + Seek + Write 句柄的Disk。虽然这个例子非常简单,但如果类型具有多个具有特征的成员,则类型可能会变得极其复杂。

我想要的是:

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

关于generics - 如何在嵌套 Rust 类型中抽象泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40929867/

相关文章:

rust - 如何在不分配的情况下使用 Read 跳过 N 个字节?

c# - 如何形成我的节点和树通用类

c# - 通用类和 IEquatable 问题

java - 如何在java中使用引用自类型的抽象方法创建接口(interface)

c# - 如何在 C# 中直接调用嵌套的 xml 元素

generics - 为什么我的 FooGen 类型不满足 RefGen 特征界限?

generics - `generic::write(formatted)` gfortran 中的子例程被其他派生类型调用

javascript - 从另一个 JS 返回 Html 内的 Javascript 值

sql-server - 如何在多个存储过程上使用事务?

rust - 作为参数传递的引用未移动