(一)继承范例
1、范例一:
1 pulic class Doctor{ 2 boolean worksAtHospital; 3 void treatPatient(){ 4 //执行检查 5 } 6 } 7 public class FamilyDoctor extends Doctor{ 8 boolean makesHouseCalls; 9 void giveAdvice(){ 10 //提出诊断 11 } 12 } 13 public class Surgeon extends Doctor{ 14 void treatPatient(){ 15 //进行手术(重写了父类的该方法) 16 } 17 void makeIncision(){ 18 //截肢 19 } 20 }
2、范例二:设计动物仿真程序的继承树
有狮子、犀牛、老虎、狗、猫、狼六种动物,设计过程如下。
(1)找出具有共同属性和行为的对象,用继承来防止子类中出现重复的程序代码;有5个实例变量:picture(动物图片的名称),food(动物所吃的食物),hunger(代表饥饿程度的int值),boundaries(代表动物活动范围区域的长宽),location(动物在活动区域中的X与Y坐标);还有4个方法:makeNoise():动物发出声音的行为程序;eat():动物遇到事物时的行为程序;sleep():睡眠的行为程序;roam():不在进食或睡眠时候的行为程序(注:roam,漫步)
(2)设计代表共同状态与行为的类(父类)——Animal,Animal中包含了①中的共同属性和行为;
(3)决定子类是否需要让某项行为(也就是方法的实现)有特定不同的运作方式,比如对于eat()方法,有些动物吃素,有些动物吃肉,那么不同的动物就要重写父类的这个方法。
(4)通过寻找使用共同行为的子类来找出更多抽象化的机会,比如猫和老虎和狮子都属于猫科动物,狗和狼都属于犬科动物,那么可以抽象出猫科动物类和犬科动物类。
(5)完成类的继承层次。
(二)继承的方法调用
1、最低阶原则
调用对象引用的方法时,会调用到与该对象类型最接近的方法,换句话说,会顺着继承树从下往上找起,最终会调用找到的第一个满足的方法,如下图所示(如果在继承树中都没有找到该方法,那么编译都不会通过)。
2、Has-A测试:属性测试,如狗有年龄属性。
Is-A测试:继承测试,测试继承结构的合理性,如猫是动物—>cat extends Animal
注:继承概念下的Is-A是个单向的关系,方向不能反。如猫是动物,但动物不一定是猫。
3、如果子类不想完全覆盖掉父类的某个方法,而是在父类的该方法上再增添内容,那么可以在子类的方法中使用super,例如:
1 public class Animal{ 2 public void walk(){ 3 //Animal的通用walk行为 4 } 5 //... 6 } 7 public class Cat extends Animal{ 8 public void walk(){ 9 super.walk(); 10 //Cat独有的其他walk行为 11 } 12 }
4、继承的权限
(1)下面这4种权限,左边是最受限制的,越往右边限制程度越小。
private default protected public
(2)public类型的成员会被继承,private类型的成员不会被继承。任一类的成员包含有自己定义出来的变量和方法,再加上从父类继承下来的任何东西。
(三)继承的其他总结
1、继承的意义
(1)避免了重复的程序代码;
(2)定义出共同的协议,也就是类的对象之间共同遵守的”合约“。继承可以确保某个父类型之下的所有类都会有父类所持有的全部可继承的方法。
2、继承VS组合
(1)组合即为不使用继承,而是在类中先创建其他类的对象,再通过其他类的对象调用其方法,实现代码的复用。
(2)组合比继承更灵活一些。
(3)“is-a”的关系使用继承,如“鸟是动物”鸟类用继承,继承动物类。“have-a”的关系使用组合,如“鸟有爪子”,鸟类用组合,组合爪子类。
(四)多态的基本概念
1、一般声明引用和创建对象的方法:三步曲,重点在于引用类型与对象的类型要相符,在下面的例子中两者都为Dog。
(1)声明一个引用变量(创建遥控器)
(2)创建对象(在堆上创建对象)
(3)连接对象和引用(设定遥控器)
2、在多态下,引用与对象可以是不同的类型,如: Animal myDog = new Dog(); 在运用多态时,引用类型可以是实际对象类型的父类。
3、参数和返回类型也可以多态:
1 //参数多态: 2 public void doWalk(Animal a){ 3 a.walk(); 4 } 5 //参数a为Animal类型,调用doWalk方法时,参数可以为Animal的任一子类的对象。 6 7 //返回类型多态: 8 public Animal getSomething( ){ 9 Dog d = new Dog( ); 10 //一些代码... 11 return d; 12 } 13 //通过多态,可以编写出引进新型子类时也不必修改的程序。
4、遵守合约:覆盖的规则
(1)参数必须要一样,且返回类型必须要兼容;
(2)不能降低方法的存取权限,如从public改为private就是降低了权限。
5、设计子类最多能设计多少层?
A:没有严格层数规定,但建议层次少一点比较好。
6、有三种方法可以防止某个类被做出子类:
第1种是存取控制:非public的类只能被同一个包的类做出子类;
第2种是使用final修饰类,这表示该类是继承树的末端,不能被继承;
第3种是让类只拥有private的构造方法。
注:将整个类标识为final表示没有任何的方法可以被覆盖。
7、方法的重载
(1)普通方法和构造方法都可以重载。
(2)定义:是指同一个类中可以定义有相同的名字但参数不同的多个方法。调用时会根据不同的参数表选择对应的方法。
(3)两同三不同:同一个类,同一个方法名;参数列表参数的类型、个数、顺序不同。
(4)只有返回值类型不同不构成重载!只有形参名称不同也不构成重载!
(5)典型的方法重载:
1 System.out.println(String str); 2 System.out.println(int i); 3 System.out.println(double d); 4 System.out.println();
8、方法的重载(overload)与多态:重载的意义是两个方法的名称相同,但参数不同,所以重载与多态毫无关系。重载的方法与覆盖的方法不一样。
9、方法的重写
(1)与重载没有半毛钱关系!
(2)在子类中可以根据需要对从基类继承来的方法进行重写。
(3)重写方法必须和被重写的方法具有相同的方法名称、返回值和参数列表。
【本章结束】