继承与多态
1,继承的基本原理
例如:交通工具—>汽车—>小汽
箭头后的车子都是由箭头前继承来的
子类会自动拥有父类的属性和方法,同时可以加入自身的一些特性,使得它
更具体、功能更强。
分类:
多重继承:两个或两个以上的父类
单一继承:最多只有一个父类
2,子类对父类的继承
一个类 B 继承了已有的类 A,则称 A 是 B 的父类,也称超类或基类。而 B 是
A 的子类,也称派生类。在子类声明中,用关键字 extends 来指出其父类
基本格式:
class 子类 extends 父类 {
}
*使用 extends 指定父类.
*Java 中一个子类只能继承一个父类 (而 C++/Python 等语言支持多继承).
*子类会继承父类的所有 public 的字段和方法.
*对于父类的 private 的字段和方法, 子类中是无法访问的.
*子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类
实例的引用
// Animal.java
public class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
// Cat.java
class Cat {
public String name;
public Cat(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
// Bird.java
class Bird {
public String name;
public Bird(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
public void fly() {
System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
}
}
这个代码我们发现其中存在了大量的冗余代码.
仔细分析, 我们发 Animal 和 Cat 以及 Bird 这几个类中存在一定的关联关系:
这三个类都具备一个相同的 eat 方法, 而且行为是完全一样的.
这三个类都具备一个相同的 name 属性, 而且意义是完全一样的.
从逻辑上讲, Cat 和 Bird 都是一种 Animal (is - a 语义).
此时我们就可以让 Cat 和 Bird 分别继承 Animal 类, 来达到代码重用的效果.
注意:继承具有传递性
对于上面的代码, 可以使用继承进行改进. 此时我们让 Cat 和 Bird 继承自
Animal 类, 那么 Cat 在定义的时候就不必再写 name 字段和 eat 方法
class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
class Cat extends Animal {
public Cat(String name) {
// 使用 super 调用父类的构造方法.
super(name);
}
}
class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void fly() {
System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("小黑");
cat.eat("猫粮");
Bird bird = new Bird("圆圆");
bird.fly();
}
}
3,属性隐藏和方法的覆盖
1)属性的隐藏
只要子类中的成员
量与父类同名,就可以将父类的隐藏起来。一般情况下
使用的是子类的同名变量
2)方法的覆盖
子类中,如果觉得继承下来的方法不能满足自己的需要,可以将其重写一遍,
这被称为覆盖。覆盖必须满足两个方面:
*方法名必须相同
*方法的参数必须完全相同,包括参数的个数,类型和顺序
final 关键字
曾经我们学习过 final 关键字, 修饰一个变量或者字段的时候, 表示常量
(不能修改).
final int a = 10;
a = 20; // 编译出错
final 关键字也能修饰类, 此时表示被修饰的类就不能被继承.
final public class Animal {
...
}
public class Bird extends Animal {
...
}
// 编译出错
Error:(3, 27) java: 无法从最终 com.bit.Animal 进行继承
4,构造方法的继承
1)无参数构造方法的继承:
这种方法与普通方法的继承本质并不相同,它其实是一种自动调用
2)带参数的构造方法的继承:
带参数的构造方法,不会由子类继承,也不会自动调用
3)无参数构造方法的覆盖:
带参数的构造方法不会被继承,也不存在覆盖问题。只有无参的构造方法才
存在覆盖问题。java 规定,子类中无论是哪个构造方法在执行时,都会先执行
父类中无参数的构造方法。
5,super 的使用
如果想在子类中访问父类的成员,就需要用到关键字 super
用法如下:
super.变量名;
super.方法名([参数列表]);
super.([参数列表]);
class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
class Cat extends Animal {
public Cat(String name) {
// 使用 super 调用父类的构造方法.
super(name);
}
}
注意:
*它只能用在构造方法中
*它只能是第一条执行语句
*一个构造方法中只能有一条 super 语句
6,多态的基本概念
多态性指一个名词有多种语义,在 OOP 当中,多态不仅指这一种情况,还与类密切相关。同一类的所有对象在收到同一条消息时,将采取同样的动作,而不同类对象在收到同一消息时,可能采取不同动作。
java 的多态性,主要通过继承中的覆盖和方法的重载来实现。前者还可以通过“动态绑定”技术实现运行时多态,后者则使用“静态绑定”技术实现多态。
7,重载
java 允许在一个类中,多个方法拥有相同名字,但在名字相同的同时,必须有不同的参数,这就是重载
1)普通方法的重载
当方法名不同时,为了让编译器区别,至少需要下面之一不同:
*参数个数不同
*对应位置上的参数类型不同
2)构造方法的重载
相对于普通的成员方法,由于构造方法不能是 static 和 final 类型,而且也没有返回值,所以它的重载比普通成员方法更简单一些,但一般的规则完全相同。
3)重载与覆盖的区别
*重载和覆盖的方法名称都相同,但重载要求参数列表不同,而覆盖要求参数列表完全相同;
*重载对于方法面前的修饰符没有限制,而覆盖则对于这些修饰符的使用有限制;
*同一类中的方法能够互相重载,但不能互相覆盖。子类对于父类的方法既可以重载也可以覆盖;
*重载时,编译器在编译期间就可以确定调用哪一个方法,而覆盖则可能在运行期间才能确定;