Enums 图书馆作者最喜欢的子类型选择是什么?为什么?
我有两种类型,Enums 图书馆作者最喜欢的子类型选择是什么?为什么?,enums,rust,polymorphism,traits,subtype,Enums,Rust,Polymorphism,Traits,Subtype,我有两种类型,A和B,它们共享一个公共接口T。我想通过接口T编写既能使用A又能使用B的函数 < C++ >中,我将 T 为代码< A/和代码> B/COD>的抽象超类,并编写函数接受类型 t > 在锈病方面,我似乎有两个很好的解决方案 枚举类型 在T的方法中,我可以匹配变量以专门化类型,然后在访问变量成员时编写我想要的任何内容。 然后,我可以编写直接接受T类型参数的函数: fn f(t: T) { // I can use t.method here } 特点 对于traits,类型
A
和B
,它们共享一个公共接口T
。我想通过接口T
编写既能使用A
又能使用B
的函数
< C++ >中,我将<代码> T <代码>为代码< A/<代码>和代码> B/COD>的抽象超类,并编写函数接受类型<代码> t<代码> >
在锈病方面,我似乎有两个很好的解决方案
枚举类型
在T
的方法中,我可以匹配变量以专门化类型,然后在访问变量成员时编写我想要的任何内容。
然后,我可以编写直接接受T
类型参数的函数:
fn f(t: T) {
// I can use t.method here
}
特点
对于traits,类型已经在方法定义中专门化了。但是,要使用T.method
,我需要编写一个通用函数:
fn f<X: T>(t: X) {
// I can use t.method here
}
fn f(t:X){
//我可以在这里使用t方法
}
这里让我感到困扰的是,虽然这两种解决方案都能完美地工作,但实现是公开的:f
的签名在这两个示例中是不同的。如果我编写了一个带有枚举的库,但最终决定我真正想要的是traits,那么每个用户级别的类型签名都需要更改
鉴于这一事实,图书馆作者选择了什么样的选择,为什么
<>请注意,我不特别关心继承,我不想把C++习语导入锈,我想知道更好的选择是什么。
图书馆作者喜欢使用枚举还是特征
建筑工人喜欢用钉子或螺丝钉吗
医生喜欢使用胶水、缝线或订书钉吗
这是一种荒谬的二分法。这两种能力都存在,并且都在使用。人们为手头的特定工作使用正确的工具
首先回顾并重读这一章
简言之,特征允许无限多态性,而枚举是严格有界的。真的,这就是主要的区别。回顾你的问题领域需要什么,并使用正确的东西
实现是公开的:f
的签名在两个示例中都不同
是的,设计软件有时需要一些前期的思考、关注和设计
如果向用户公开枚举,然后添加、删除或修改变量,则需要更新该枚举的每次使用
如果您向用户公开一个特性,然后添加、删除或修改一个方法,那么该特性的每个用法都需要更新
在导致此问题的枚举或特征之间进行选择并没有什么特别的。您还可以重命名方法、添加、删除或重新排列参数。有很多方法会给用户带来麻烦
如果更改API,您的用户将受到影响
我需要写一个泛型函数
您不需要这样做,但出于性能原因,您可能应该默认使用它。如果
引起惊愕,可以使用特征对象,如fn f(t:&t)
或fn f(t:Box)
用enum编写一个库,但最终确定我真正想要的是traits
既然您知道不必总是选择其中一个,也要意识到您可以将它们一起使用:
enum Pet {
Cat,
Dog,
Other(Box<Animal>),
}
trait Animal {}
就个人观点而言,如果我仍然在原型化我的代码,并且不清楚哪种选择更好,我可能会默认使用特性。无界多态性更符合我对依赖注入和测试风格的偏好。从你回答的防御语气来看,你似乎将我的问题解释为生锈,而事实并非如此;我知道C++比锈少,所以也许比较不是最好的。多亏了指向无界/有界多态性的指针,我将对此进行研究。作为一个具体的例子,我正在构建一个光线跟踪器,它支持可以在空间中定位和渲染的形状。我将有一个用于定位属性的“Transform”数据类型和一个用于渲染属性的“Material”数据类型。然后,我可以将形状实现为包含这些数据类型的结构和类型enum(Sphere、Cube、Mesh等)。或者,我可以有一个“形状”特征(或者可能是“交叉的”),并让不同的形状类型实现这个特征。在这种情况下,两种选择的取舍是什么?@yawn我本不打算防御性的,但我的意思是(以轻松的方式)传达少量的烦恼/挫折。当一个问题预设了世界的某个状态时,这是令人恼火的,因为这样一来,答案就必须花时间撕毁这个信念,回到基础上来,然后再从那里建立起来。在本例中,我看到了两个选项:“枚举和特征在功能上是可交换的”和“枚举和特征之间的选择会影响我的用户”。然而,最好了解这个最初的世界观,这样才不会意外地妨碍理解。
fn f<X: T>(t: X) {
// I can use t.method here
}
enum Pet {
Cat,
Dog,
Other(Box<Animal>),
}
trait Animal {}
trait TimeSource {
fn now() -> u64;
}
enum Builtin {
Ntp,
Sundial,
}
impl TimeSource for Builtin {
// ...
}