Rust用组合实现java中的继承重写
2015-08-22 12:55
531 查看
先来看看Java的继承和重写是怎么做的吧!
##Java继承的示例
输出:
抛开面向对象的思想,从语法的角度来分析,可以看到:我们通过继承在Student这个类型上调用到了Person这个类型中的方法。从而复用了Person类的代码。
但有的时候我们需要重写父类的方法,一个学生的介绍可能不同于其它人。这就需要重写父类方法:
输出:
##Rust中用Deref和DerefMut特性实现Java的继承
编译出错:
说明通过简单的包含不会达到继承的效果。要能访问到Person中的方法,我们还需要为Student实现一个特性:
编译输出:
可以看出,通过实现Deref特性,我们可以模拟继承,在Student类型的对象上调用Person类型的方法。
看到上面我们的输出,Student没有名字,这怎么可以,我们来把名字给加上,很简单,修改main函数如下:
编译输出:
实现了Deref特性后,我们确实可以访问到Person的方法了,但是不能修改他的属性!为什么?我的stu对象已经用mut修饰了,成员p应该是可以修改的呀!
原因很简单,通过这种方法来访问Person是利用了Rust中叫Auto-Deref的规则来实现:在stu调用一个Student类没有提供的方法setName,编译器会自动调用stu的deref方法,并在返回的类型上继续寻找该方法,直到找到方法或者是返回的类型不能被deref。
之所以会出这个错误,是因为stu的deref方法返回的&'a Person类型,是一个不可变的引用。要让main函数可以工作,我们就还需要实现另一个特性:
编译输出:
Oh Yeah!成功!
通过Deref与DerefMut特性,我们实现了Java中的继承。
##Rust重写Person类型的方法
这个很简单,根据上面的Auto-Deref规则描述,只要在Student中定义一个签名相同的方法就可以了。
编译输出:
Rust 是一门很棒的语言,你值得拥有!
##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 是一门很棒的语言,你值得拥有!
相关文章推荐