Java中类和接口
里氏代换原则是什么?听起来很高深,不过我们也不是什么学院派,就不讲大道理了,直接拿个例子来说一下。
我们拿人和程序员举个例子。人是一个大类,程序员是继承自人的子类。看看这句话:人需要吃饭。这句话我们把“人”换成“程序员”,就是:程序员需要吃饭,这样换不会有什么问题。现在我们反过来,把“程序员可以用计算机写程序”里边的程序员换成“人”,就是:人可以用计算机写程序。这样就不一定正确了,否则问题可就大了,我们这些程序员只怕没得饭吃了。
这个就是里氏代换原则:使用父类的地方肯定可以用它的一个子类来替换掉,但是使用一个子类的时候用它的父类来替换就不一定正确了。
好,现在我们回到程序设计里边来。
看看下面的程序:
一个学校里边,有两种人:学生、老师。他们都要吃饭和睡觉。
public interface 人{
void 吃饭();
void 睡觉();
}
public class 学生 implements 人{
public void 吃饭(){
//去食堂吃饭
}
public void 睡觉(){
//回寝室睡觉
}
...//其他特有方法,比如泡妞、打游戏
}
public class 老师 implements 人{
public void 吃饭(){
//回家吃饭
}
public void 睡觉(){
//回家睡觉
}
...//其它特有方法,比如为生儿育女传宗接代的历史使命努力等不足为外人道的事情
}
public class 学校{
public void 开饭(人 ren){
ren.吃饭();
}
public void 放学(人 ren){
ren.睡觉();
}
}
这里就用到了里氏代换原则,"开饭()"和"放学()"的参数都是人,那么这个地方如果换成学生和老师肯定也可以。
人 a = new 学生();
学校.开饭(a);
学校.放学(a);
这样执行的结果就是学生回寝室吃饭。
人 b = new 老师();
学校.开饭(b);
学校.放学(b);
这样执行的结果就是老师回家吃饭。
为什么要这样写呢?这样写有什么好处呢?
我在开饭的时候完全可以直接调用"学生.吃饭();"、"老师.吃饭();"啊。
接着看。
有一天,学校里来了第三种人,家长。
家长既不是去寝室睡觉也不是回家睡觉,而是旅馆睡觉,既不是去食堂吃饭也不是回家吃饭,而是去下馆子。
这个时候学校这个系统该怎么处理呢?
如果原来没有定义"人"这个接口那就麻烦啦,所有用到人的地方代码都要改。
现在不一样了,我可以直接定义一个类:家长,这个类实现人这个接口就可以了。
好,看代码:
public class 家长 implements 人{
public void 吃饭(){
//下馆子
}
public void 睡觉(){
//去旅馆睡觉
}
...//其它特有方法,比如会见老师,晓之以钱,动之以利等等,不一而足
}
在调用的时候不需要修改任何代码,还和原来一样:
人 c=new 家长();
学校.开饭(c);
学校.放学(c);
轻松搞定家长的食宿问题!
这样一来学校来再多的客人都没关系啊,绝对可以应付自如,这也就是传说中的可扩展性!
不知道初学者看到这里是不是能够明白接口的作用。如果你还不明白,那么你把人这个接口去掉,自己写一个学校开饭和放学的类,然后再加一个家长这个新新人类进去,看看你的代码是什么样子的,再想一下在人口这么多的中国,万一哪天你的学校里来了成千上万个新新人类你该怎么办!
1 interface
Runner //定义接口
2 {
3 int
i=3;
4 public
void start();
5 void
run();
6 void
stop();
7 }
8 interface Eater extends
Runner //接口间可以继承
9 {
10 public
final static int j=4;
11 void
openMouth();
12 void
upAndDown();
13 void
goIn();
14 }
15 class
TT implements Eater //引用接口
16 {
17 public
void start()
18 {
19
System.out.println("---------start()-------");
20 }
21 public
void run()
22 {
23
System.out.println("---------run()-------");
24 }
25 public
void stop()
26 {
27
System.out.println("---------stop()-------");
28 }
29 public
void openMouth()
30 {
31
System.out.println("---------openMouth()-------");
32 }
33 public
void upAndDown()
34 {
35
System.out.println("---------upAndDown()-------");
36 }
37 public
void goIn()
38 {
39
System.out.println("---------goIn()-------");
40 }
41 }
42 public
class TestInterface
43 {
44 public
static void
main(String[] args)
45 {
46 Runner tt=new TT();//接口的引用指向实现的对象
47 System.out.println(tt.i);
48 System.out.println(Runner.i);
49 tt.start();
50 Eater ee=new TT();
51 System.out.println(ee.j);
52 System.out.println(Eater.j);
53 ee.start();
54 }
55 }
接口的应用2:
1 public class
TestInterface {
2
3 public
static void
main(String[] args){
4
5 CareAnimalable c = new Worker();
6 //Worker
w = (Worker)c;
7 TestInterface t = new TestInterface();
8 t.t(c); //多态
9
10 c = new
Farmer();
11 t.t(c);
12
13
14
}
15
16
public void
t(CareAnimalable c){//尽量定义为接口或父类的引用
17 c.feed();
18 c.play();
19
}
20 }
21
22
23 interface
CareAnimalable{
24
public void
feed();
25
public void
play();
26 }
27
28 class Worker
implements CareAnimalable{
29
30
public void
feed(){
31
System.out.println("-----feed()----");
32
}
33
34
public void
play(){
35
System.out.println("-----play()----");
36
}
37 }
38
39 class Farmer
implements CareAnimalable{
40
41
public void
feed(){
42
System.out.println("-----Farmer feed()----");
43
}
44
45
public void
play(){
46
System.out.println("-----Farmer play()----");
47
}
48 }
最新文章
- [LeetCode] One Edit Distance 一个编辑距离
- ie6下js更新元素display:block后,仍然不显示的hack办法
- 关于处理小数点位数的几个oracle函数
- 20 seq 某个数到另外一个数之间的所有整数
- LR11.0 下载及破解
- 多线程java代码移植到android&;下载文本界面的更新
- Crowd安装和破解
- Azure IoT 技术研究系列4-Azure IoT Hub的配额及缩放级别
- java 分解质因数
- [搬运] C# 这些年来受欢迎的特性
- MySql Query Cache 优化
- 如何在微信小程序定义全局变量、全局函数、如何实现 函数复用 模块化开发等问题详解
- 从GitHub下载demo时遇到的依赖问题
- obfuscate 混淆 verb
- Jsの练习-数组其他常用方法 -map() ,filter() ,every() ,some()
- lnmp或者lamp环境一键安装
- 735. Asteroid Collision彗星相撞后的消失数组
- 急速JavaScript全栈教程
- (转)java 层调用Jni(Ndk) 持久化c c++ 对象
- js图的数据结构处理---弗洛伊德算法