继承与多态
了解继承
继承的关系意味着子类继承了父类的实例变量和方法。
父类比较抽象,子类比较具体。
继承层次的设计
- 找出具有共同属性和行为的对象(用继承来防止子类中出现重复的程序代码)
- 设计代表共同状态与行为的类
- 决定子类是否需要让某项行为(也就是方法的实现)有特定不同的运行方式,即方法由子类覆盖
- 通过寻找使用共同行为的子类来找出更多抽象化的机会。
“是一个”与”有一个”
当一个类继承自另外一个类时,我们会说这是子类去继承父类。若你想要知道某物是否应该要继承另一物时,则可以用is-a测试来检验。
is-a测试适用在继承层次的任何地方。如果你的继承层次树设计得很好,那么多有的子类都应该通过任意个上层父类的IS-A测试。
如果类Y是继承自类X,且类Y是类Z的父类,那么Z应该能够通过IS-A X的测试。
子类能继承下来哪些东西?
4种权限:private default protected public
存取权限(access level)控制了谁可以接触什么。
public类型的成员会被继承
private类型的成员不会被继承
要点:
- 子类是extends父类出来的
- 子类会继承父类所有public类型的实例变量和方法,但不会继承父类所有private类型的变量和方法
- 继承下来的方法可以被覆盖掉,但实例变量不会被覆盖掉
- 使用is-a测试来验证继承结构的合理性
- is-a关系是单方向的。河马是动物,但动物不一定是河马
- 当某个方法在子类中被覆盖过,调用这个方法会调用到覆盖过的版本
- 如果类Y是extends类X,且类Y是类Z的父类,则Z应该能通过IS-A X的测试。
继承的意义
通过设计继承的过程累积面向对象的经验值。
通过提取出一组类间共同的抽象性,能够排除掉重复的程序代码而将这个部分放在父类,如此一来,如果有共同的部分需要修改,那么就只需改一个地方,不需要动子类。
- 避免重复的程序代码
- 定出共同的协议
多态
多态下,引用类型与对象可以是不同的类型
运用多态时,引用类型可以是实际对象类型的父类
参数和返回类型也可以多态,如果方法参数声明为父类类型,那么在运行时可以传入任何的子类对象。
问题
你能够继承任何一个类么?就像类的成员一样如果类是私有的你就不能继承?
有三种方法可以防止某个类被作为子类
第一种是存取控制:就算类不能标记为私有的,但它还是可以不标记公有。非公有的类只能被同一个包的类作出子类。
第二种是使用final这个修饰符,这表示它是继承的末端,不能被继承
第三种是让类只拥有private的构造程序
为什么会做出标识final的类,这样有什么好处?
一般来说,不会标识final,但如果需要安全-确保方法都是你写的版本,此时就需要final
可不可以只用final去标识方法而不是用整个类
如果想防止特定的方法被覆盖,可以将该方法标识上final这个修饰符,将整个类标识为final表示没有任何的方法可以被覆盖
覆盖的规则
- 参数必须要一样,且返回类型必须要兼容
- 不能降低方法的存取权限:存取权限必须相同,或者更为开放。
方法的重载(overload)
重载的意义是两个方法的名称相同,但参数不同,所以重载与多态毫无关系
重载版的方法只是刚好有相同名字的不同方法,它与继承或多态无关,重载的方法与覆盖方法不一样。
- 返回类型可以不同
- 不能只改变返回类型
- 可以更改存取权限