本篇博客将介绍Java中的继承。
我们可以先来看这样一段代码:
class Dog {
public String name;
public int age;
public void eat() {
System.out.println("吃");
}
}
class Bird {
public String name;
public int age;
public void eat() {
System.out.println("吃");
}
public void fly() {
System.out.println("飞");
}
}
我们可以发现,这两个类存在很多共性,比如都有name,age,还有eat方法。那么我们能不能想个办法,把这些共性放到一起,如果以后有需要,直接调用即可。这种方法是存在的,它就是我们今天要讲的继承。
继承是对共性的抽取,使用extends关键字进行处理的。 例如:
class Animal {
public String name;
public int age;
public void eat() {
System.out.println("吃");
}
}
class Dog extends Animal {
}
class Bird extends Animal {
public void fly() {
System.out.println("飞");
}
}
此时,Dog和Bird被称为 子类 或 派生类 。Animal被称为 父类 、 基类 或 超类 。extends就代表 继承 。
从逻辑上讲, Dog 和 Bird 都是一种 Animal (is - a 语义)。
继承的意义:可以对代码重复使用。
class 子类 extends 父类 {
}
注意事项:
使用 extends 指定父类。
Java 中一个子类只能继承一个父类(而C++/Python等语言支持多继承)。
子类会继承父类的所有 public 的字段和方法。
对于父类的 private 的字段和方法,子类中是无法访问的。
子类的实例中,也包含着父类的实例。可以使用 super 关键字得到父类实例的引用。
子类构造的同时,要先帮助父类来进行构造。例如:
class Animal {
public String name;
public int age;
public void eat() {
System.out.println("吃");
}
}
class Dog extends Animal {
public Dog(String name, int age) {
super(name,age);//调用父类带有两个参数的构造方法
}
}
class Bird extends Animal {
public String wing;
public Bird(String name,int age,String wing) {
super(name,age);
this.wing = wing;
}
public void fly() {
System.out.println(super.name + "飞" + super.age);
}
}
super不能出现在静态方法当中。
例如:
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "吃" +food);
}
}
class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void fly() {
System.out.println(name + "飞");
}
}
小结:
private:类内部能访问,类外部不能访问。
默认(也叫包访问权限):类内部能访问,同一个包中的类可以访问,其他类不能访问。
protected:类内部能访问,子类和同一个包中的类可以访问,其他类不能访问。
public:类内部和类的调用者都能访问。
什么时候下用哪一种呢?
我们希望类要尽量做到 “封装”,即隐藏内部实现细节,只暴露出 必要 的信息给类的调用者。因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限。例如,如果一个方法能用 private,就尽量不要用public。
另外,还有一种 简单粗暴 的做法:将所有的字段设为 private,将所有的方法设为 public。不过这种方式属于是对访问权限的滥用, 还是更希望大家能写代码的时候认真思考,该类提供的字段方法到底给 “谁” 使用(是类内部自己用,还是类的调用者使用,还是子类使用)。
时刻牢记,我们写的类是现实事物的抽象。而我们真正在公司中所遇到的项目往往业务比较复杂,可能会涉及到一系列复杂的概念,都需要我们使用代码来表示,所以我们真实项目中所写的类也会有很多. 类之间的关系也会更加复杂。但是即使如此,我们并不希望类之间的继承层次太复杂。一般我们不希望出现超过三层的继承关系。如果继承层次太多,就需要考虑对代码进行重构了。如果想从语法上进行限制继承,就可以使用 final 关键字。
例如:
final public class Animal {
...
}
public class Bird extends Animal {
...//编译错误
}
组合与继承类似,但却有所不同。我们可以看个例子:
public class Student {
...
}
public class Teacher {
...
}
public class School {
public Student[] students;
public Teacher[] teachers;
}
由此可知,组合也是一种表达类之间关系的方式,也是能够达到代码重用的效果。但是组合并没有涉及到特殊的语法(诸如 extends 这样的关键字),仅仅是将一个类的实例作为另外一个类的字段。这是我们设计类的一种常用方式之一。
本篇博客到此结束
上一篇博客:Java学习苦旅(十一)——你好,买“包”不?
下一篇博客预告:Java学习苦旅(十三)——多态