您的位置:首页 > 编程语言 > Java开发

Rust用组合实现java中的继承重写

2015-08-22 12:55 531 查看
先来看看Java的继承和重写是怎么做的吧!

##Java继承的示例

class Person{
private String name;

public void setName(String name){
this.name = name;
}

public void say() {
System.out.println("我是一个人,名字叫" + this.name);
}
}

// 学生继承人的属性的方法
// 添加了自己的属性和方法
class Student extends Person{
private String role;

public void setRole(String role) {
this.role = role;
}
}

public class Demo01{
public static void main(String args[]){
Student stu = new Student();
stu.setName("曾赛");
stu.setRole("班长");
stu.say();
}
}

输出:

我是一个人,名字叫曾赛

抛开面向对象的思想,从语法的角度来分析,可以看到:我们通过继承在Student这个类型上调用到了Person这个类型中的方法。从而复用了Person类的代码。

但有的时候我们需要重写父类的方法,一个学生的介绍可能不同于其它人。这就需要重写父类方法:

class Person{
private String name;

public void setName(String name){
this.name = name;
}

public void say() {
System.out.println("我是一个人,名字叫" + this.name);
}
}

// 学生继承人的属性的方法
// 添加了自己的属性和方法
class Student extends Person{
private String role;

public void setRole(String role) {
this.role = role;
}

public void say() {
System.out.println("我是一个学生,名字叫" + this.name +",担任" + this.role);
}

}

public class Demo01{
public static void main(String args[]){
Student stu = new Student();
stu.setName("曾赛");
stu.setRole("班长");
stu.say();
}
}

输出:

我是一个学生,名字叫曾赛,担任班长

##Rust中用Deref和DerefMut特性实现Java的继承

struct Person {
name: String,
}

impl Person {
fn setName(&mut self, name: &str) {
self.name = name.to_string();
}

fn say(&self) {
println!("我是一个人,名字叫{}", self.name);
}
}

struct Student {
p: Person,
role: String,
}

impl Student {
fn new() -> Student {
Student {
p: Person {
name:"没有名字".to_string()
},
role:"普通学生".to_string()
}
}

fn setRole(&mut self, role: &str) {
self.role = role.into()
}
}

fn main() {
let mut stu = Student::new();
stu.setRole("班长");
stu.say();
}

编译出错:

obj.rs:38:9: 38:14 error: no method named `say` found for type `Student` in the current scope
obj.rs:38     stu.say();
^~~~~
error: aborting due to previous error

说明通过简单的包含不会达到继承的效果。要能访问到Person中的方法,我们还需要为Student实现一个特性:

use std::ops::Deref;

impl Deref for Student {
type Target = Person;

fn deref<'a>(&'a self) -> &'a Person {
&self.p
}
}

编译输出:

我是一个人,名字叫没有名字

可以看出,通过实现Deref特性,我们可以模拟继承,在Student类型的对象上调用Person类型的方法。

看到上面我们的输出,Student没有名字,这怎么可以,我们来把名字给加上,很简单,修改main函数如下:

fn main() {
let mut stu = Student::new();
stu.setName("曾赛");
stu.setRole("班长");
stu.say();
}

编译输出:

obj.rs:47:5: 47:8 error: cannot borrow immutable borrowed content as mutable
obj.rs:47     stu.setName("曾赛");
^~~
error: aborting due to previous error

实现了Deref特性后,我们确实可以访问到Person的方法了,但是不能修改他的属性!为什么?我的stu对象已经用mut修饰了,成员p应该是可以修改的呀!

原因很简单,通过这种方法来访问Person是利用了Rust中叫Auto-Deref的规则来实现:在stu调用一个Student类没有提供的方法setName,编译器会自动调用stu的deref方法,并在返回的类型上继续寻找该方法,直到找到方法或者是返回的类型不能被deref。

之所以会出这个错误,是因为stu的deref方法返回的&'a Person类型,是一个不可变的引用。要让main函数可以工作,我们就还需要实现另一个特性:

use std::ops::DerefMut;

impl DerefMut for Student {
fn deref_mut<'a>(&'a mut self) -> &'a mut Person {
&mut self.p
}
}

编译输出:

我是一个人,名字叫曾赛

Oh Yeah!成功!

通过Deref与DerefMut特性,我们实现了Java中的继承。

##Rust重写Person类型的方法

这个很简单,根据上面的Auto-Deref规则描述,只要在Student中定义一个签名相同的方法就可以了。

impl Student {
......
fn say(&self) {
println!("我是一个学生,名字叫{},担任{}", self.name, self.role);
}

编译输出:

我是一个学生,名字叫曾赛,担任班长

Rust 是一门很棒的语言,你值得拥有!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  rust auto-deref Deref