Inheritance 当Rust不再';你没有继承权吗?

Inheritance 当Rust不再';你没有继承权吗?,inheritance,rust,semantic-versioning,Inheritance,Rust,Semantic Versioning,我有使用SemVer进行版本控制的数据。我有一些功能,比如Switter的需求,比如它们支持半开式区间[1.1,2 ]的版本。在C++中我可以做这样的事情:< /P> struct Data\u v1\u 0{ //在V1.0中添加 INTA; }; 结构数据\u v1\u 1:公共数据\u v1\u 0{ //在V1.1中添加 int b; } void foo(常量数据v1\u 0和数据){ //支持[1.0,2.0] 打印(数据a); } 空栏(常数数据和数据){ //支持[1.1,2.0

我有使用SemVer进行版本控制的数据。我有一些功能,比如Switter的需求,比如它们支持半开式区间[1.1,2 ]的版本。在C++中我可以做这样的事情:< /P>
struct Data\u v1\u 0{
//在V1.0中添加
INTA;
};
结构数据\u v1\u 1:公共数据\u v1\u 0{
//在V1.1中添加
int b;
}
void foo(常量数据v1\u 0和数据){
//支持[1.0,2.0]
打印(数据a);
}
空栏(常数数据和数据){
//支持[1.1,2.0]
打印(数据b);
}

有什么方法可以在锈病中做类似的事情吗?

你可以使用特征来实现这一点:

trait数据v1\u 0{
fn a(&self)->i32;
}
特征数据v1\u 1:DataV1\u 0{
fn b(&self)->i32;
}
结构数据{
a:i32,
b:i32,
}
数据的impl DataV1_0{
fn a(自身)->i32{
赛尔夫
}
}
数据的impl DataV1_1{
fn b(&self)->i32{
赛尔夫
}
}
fn foo(数据:&dyn数据v1\u 0){
println!((“a:{}”,data.a());
}
fn条(数据:&dyn数据v1\u 1){
println!((“b:{}”,data.b());
}

我们在这里使用trait继承来替换struct,并使用trait方法来访问字段。我的示例是只读的,但您也可以实现setter方法。

另一个解决方案是像在C中一样实现继承。我不是说您应该这样做,而是说这是一种可以考虑的可能性:

pub-struct-Data\u v1\u 0{
//在V1.0中添加
a:i32,
}
impl Data_v1_0{
fn a(自身)->i32{
赛尔夫
}
fn集合a(&mut self,a:i32){
self.a=a
}
}
发布结构数据\u v1\u 1{
扩展:数据_v1_0,
//在V1.1中添加
b:i32,
}
impl数据_v1_1{
fn b(&self)->i32{
赛尔夫
}
fn集合(多个自身,b:i32){
self.b=b
}
}
数据v1\u 1的impl Deref{
类型目标=数据_v1_0;
fn deref(&self)->&self::Target{
&自我扩展
}
}
数据v1\u 1的impl DerefMut{
fn deref_mut(&mut self)->&mut self::Target{
&多自扩展
}
}

多亏了
Deref
DerefMut
,您可以在
Data\u v1\u 1
的实例上调用
a()
set\u a()
。但是,可以使用调用它(例如
Data\u v1\u 1::a(Data)
)这是不可能的,因此用
Data\u v1\u 1
替换
Data\u v1\u 0
将是一个破坏API的更改。

如果您的结构具有私有字段,则只能从您的板条箱中构造它,因此添加新字段无论如何都是一个向后兼容的更改。请尝试避免此类侵入性结构约束。相反,请创建您的逻辑在最新版本的数据结构上操作,并在入口点和出口点应用数据迁移。随着您添加更多版本,最旧数据结构的用户将体验到最大的性能影响,而最新格式的用户将体验到零影响。您的代码将是干净的,因为它只需要支持最新的这是一个不寻常的上下文,它要求继承,但这一点与其他问题非常相似,比如如果你有一个问题没有回答,请你的问题使它更具体。其他关于继承和锈蚀的问题:以及嵌入一个结构在另一个内部,就像你的C++代码一样,OOnly似乎允许添加新字段。添加新字段是一个与semver兼容的更改,因此它看起来不像您建议的(当前?)C++解决方案最适合你自己的要求。嗯,是的。虽然你的解决方案实际上没有方法来制作一个V1.0<代码>数据< /代码>。你可以将<代码> B<代码>设置为默认值,但我想没有什么可以阻止你意外地将V1.0<代码>数据< /代码>传递到<代码> BAL()。。那么你不需要做
struct Data_v1_0s{a:i32,}struct Data_v1_1s{a:i32,b:i32,}
然后
impl Data_v1_0用于数据{/code>和
impl Data_v1_1用于数据{/code>和
impl Data_v1_v1_1;
。这将变得非常乏味!可能需要宏。@Timmm您可以轻松实现一个只实现
数据的不同结构。它不能传递到
栏中。
。我也要回应@peter hall对这个问题的评论,即最好不要有版本化的数据结构,而是使用数据迁移.如果你曾经使用过COM和版本化接口,你会体会到维护这些东西的痛苦。