2016-06-18 34 views
0

C++允许使用类子类型,这非常方便,因为您可以使用派生类为基类实现的函数。 Rust似乎没有这样的东西。该功能似乎在某些时候已经可用,但自此之后已被删除。这在Rust中是不可能的吗?如果是这样,有没有计划有这个功能?Rust中的子类型

我想要做的就是确定从另一个结构,这在C++看起来像继承结构:

struct Base { 
    int x; 
    int y; 
    void foo(int x, int y) { this->x = x; this->y = y; } 
} 

struct Derived: public Base { 
    ... 
} 

void main() { 
    Derived d; 
    d.foo(); 
} 

的方式我看它,在防锈你必须写,为了这样的事情使可用于所有“衍生”结构相同的功能:

struct Base<T> { 
    x: i32, 
    y: i32, 
    derived: T 
} 
impl<T> Base<T> { 
    fn foo(&mut self, x: i32, y: i32) { 
     self.x = x; 
     self.y = y; 
    } 
} 

我觉得做一个impl<T> for Base<T>会产生一吨的相同功能的拷贝,所以成分是不是一个真正的选择。

我应该指出,上面的实现被选中的原因很简单,它允许一个更安全的upcasting版本,无论如何我都需要这样做。

+8

铁锈甚至没有类。它为运行时多态性使用基于特征的系统。你可以添加一个你想要的东西的例子(也许用C++编写的工作代码)?然后我们可以告诉你如何将它写入Rust :) –

+0

编辑原始文章更清晰。 – eugene2k

+2

作为一名C++程序员,我觉得需要指出的是,指导原则是**优先于继承构成**,而您的示例通常被认为是反模式。继承应该只用于重写行为(又名'虚拟'函数),从非多态类继承通常是一个错误(混合两个概念:是 - 关系和代码重用)。幸运的是,Rust具有后见之明,在Rust中没有继承:) –

回答

2

使用组合而不是继承。

struct Base { 
    x: u8, 
    y: u8, 
} 

impl Base { 
    fn foo(&mut self, x: u8, y: u8) { 
     self.x = x; 
     self.y = y; 
    } 
} 

struct Derived { 
    base: Base, 
} 

impl Derived { 
    fn foo(&mut self, x: u8, y: u8) { 
     self.base.foo(x, y); 
    } 
} 

fn main() { 
    let mut d = Derived { base: Base { x: 1, y: 3 } }; 
    d.foo(5, 6); 
} 

可能做制作成分那样容易键盘继承上,虽然一个更好的工作。有a RFC旨在提供一些更好的,以及以前的讨论1,2

我认为做一个impl<T> for Base<T>会产生大量相同功能的副本,所以组合并不是真正的选择。

我不确定这个语法试图显示什么,因为Base没有泛型类型。确实,对于每个具体的类型参数集,泛型都是单态,但我没有看到/知道与C++有什么不同。我认为Rust版本会稍微轻一些,因为你不能从Derived上传到Base,所以编译器不必维护这些不变量。

所有这些都假定有一些代码可以重用。在很多情况下,您最好编写一个界面,该界面在Rust中用traits表示。您可以结合使用这两种方法 - 将小部分可重用代码作为组件提取出来,将它们集合在一起成为聚合,并实现聚合类型的特征。

+0

当你有多个派生类时,可以简化它。如果你编写一个通用的'struct Base '并添加一个'derived:T',那么你就不必在你想要实现的每个派生结构中编写'base:Base'。然后,您可以使用'impl Base '为派生结构添加impls。我正在那样做。问题是当你有一百个派生结构时会发生什么?根据我对每个Derived结构的理解,编译器将生成一个新函数,它执行相同的操作。 – eugene2k

+0

我再次澄清了这篇文章。希望它现在更有意义。 – eugene2k

0

我想答案是,在Rust中没有子类型。分型解决的问题类型不能总是通过组合,泛型或特征来解决。问题是known to the devs并提供了解决方案,但尚未确定。