head first java ( 第 7 章 )
- 了解继承
在设计继承时, 你会把共同的程序代码放在某个类中, 然后告诉其他的类说此类是它们的父类.
通过找寻使用共同行为的子类来找出更多抽象化得机会
- “是一个” 与 “有一个”
“是一个”用继承
三角形是一个多边形->OK, 澡盆是一个浴室->NG, 应该是浴室有一个澡盆( 表示浴室带有澡盆的实例对象 )
- 如果在子类中还打算引用父类的方法然后再加上额外的行为该怎么办?
答:这是可行的, 事实上这个功能非常重要, 扩充本来加以延伸. 例如 如下代码
public void roam() {
super.roam();
// my own roam stuff
}
- 继承的意义
通过提取出一组类间共同的抽象性, 你能够排除掉重复的程序代码而将这个部分放在父类中, 如此一来, 如果有共同的部分需要改变,
就只会有一个地方要修改而已, 且这样的改变会应用到所有继承此行为的类. 修改之后只需要重新编译就行, 不必动子类.
- 子类型可以用来填补父类型空缺的位置
这是必然的, 因为IS-A 的关系.
- 多态
引用与对象可以是不同类型. 例如:
Animal myDog = new Dog(); // 实际堆内分配的是 dog类型的内存, 但是因为dog 就是一个animal,
// dog可以出现在父类可以出现的任何地方.
因为引用对象实际上就是一个指针, 其实质还是在堆内存中的真正对象.
多态数组:
Animal[] animals = new Animal[5];
animals[0] = new Dog();
animals[1] = new Cat();
animals[2] = new Wolf();
for (int i = 0; i < animals.length; i++) {
animals[i].eat();
animals[i].roam();
} // 这正是多态厉害的地方, animals[0]的eat方法, 调用的是 dog的 eat方法, 而animals[1] 则调用的是 cat的方法
不仅如此, 参数和返回类型也可以多态.
- 不能被继承的类
1. 存取控制, 非公有的类只能被同一个包的类作出子类.
2. final, 这表示它是继承树的末端, 不能被继承. ( 因为这个类得作者已经觉得这个类十分完美了,不需要再被修改了,所以就会标记为final类,表示不需要被修改,或者这个类得实现细节不能被修改)
final 这个修饰符 在修饰类时, 表示不能被继承.
在修饰方法时, 表示不能被重写.
在修饰变量时, 表示该变量是常量.
3. 只拥有 private 的构造方法.
假设内部类并定义为: private final class Inner, 这个类在外部肯定是不能被继承的, 原因不是因为 private 不能被继承,
而是因为在外部, 无法看到 private 这个内部类, 看不到自然就无法继承, 而在类得内部也不能继承, 就是因为 final 这个修饰符,
如果去掉这个 final, 那么它在类得内部是可以被继承的.
- 不能被覆盖的方法
如果你想要防止特定的方法被覆盖, 可以将该方法表示上 final 这个修饰符, 将整个类标识成 final 表示没有任何的方法可以被覆盖.
这个是当然呢, 因为整个类都不能被继承了, 就根本没有办法重写这个类中的任何一个方法了. ( 当一个类被定义为 final时, 它的所有
方法都自动成为 final 方法, 但不影响对变量的定义 )
- 重写要履行合约( 覆盖 )
当你要覆盖父类的方法时, 就的履行合约, 比如, 这个合约表示”我没有参数并且返回布尔值”, 方法就是合约的标志.
所以, 要想覆盖就必须定义(重写)与父类完全一样的(方法名, 参数, 返回), 否则… 比如:
父类: public void getMoney(int num)
子类: public void getMoney(int num, String(name))
这两个方法虽然有同样的方法名, 但是很明显是两个方法, 子类的方法也不会覆盖父类的方法.
参数必须要一样, 且返回类型必须要兼容.( 子类必须要声明返回一样的类型或该类型的子类 )
子类对象的保证能够执行父类的一切.
不能降低方法的存取权限, 这代表存取权限必须相同, 或更为开放, 你不能覆盖掉一个工友的方法并将它标记为私有. 这会让它(java)以为
在编译期间通过的是个公有, 然后突然在运行期间才被java虚拟机阻止存取.
- 方法的重载
重载与多态毫无关系, 重载版得方法只是刚好有相同名字的不同方法, 它与继承或多态无关. 重载的方法与覆盖的方法不一样.
重载不需要履行父类的契约, 因为跟继承根本没啥关系.
重载的关键在参数, 如果只是改变了返回类型, 而没有改变参数, 编译器是不准许这样做的.
也可以改变存取权限( public, private 等等 )