繼承的概念
繼承體現爲兩個類之間的一般與特殊的關係。如果A類是一種特殊的B類,則A繼承B。我們將B稱爲父類,A稱爲子類。繼承使用extends關鍵字。子類繼承了父類,子類就稱爲一種特殊的父類,子類便具有了父類的功能,即子類會繼承父類的成員。
如果沒有顯式的使用extends繼承任何類,則該類隱式繼承Object類。Object是所有類的父類。任何類(除Object自身)都是Object類的直接或間接子類。
在Java中,類只支持單繼承。一個子類只能繼承一個父類。
繼承的優勢:
通過繼承,可以有效減少代碼的重複。有利於程序的維護。
public class Inherit {
public static void main(String[] args) {
Vehicle v = new Vehicle();
v.run();
Bus b = new Bus();
b.run();
}
}
class Vehicle {
public void run() {
//System.out.println("run()");
System.out.println("run1()");
}
}
//子類繼承父類之後,子類還可添加自身方法。
class Bus extends Vehicle {
//子類所特有的功能
public void openDoor() {
System.out.println("開門");
}
}
成員的繼承
當子類與父類在同一個包中時,子類可以繼承父類public, protected, 默認訪問權限的成員。不能繼承private訪問權限的成員。
當子類與父類不在同一個包中時,子類可以繼承父類public,protected訪問權限的成員,不能繼承默認的,private訪問權限的成員。
構造器不是方法,也不是類的成員。構造器不能被子類繼承。
//同一個包中
package com.lvamber;
public class A {
public int a;
protected int b;
int c;
private int d;
public void a() {
}
protected void b() {
}
void c() {
}
private void d() {
}
public A() {
System.out.println("構造器");
}
}
class A extends B {
public void access() {
//this.a = 1;
a = 1;
b = 1;
c = 1;
//d = 1;
a();
b();
c();
//d();
//錯誤
//new B();
}
public B(int x) {
}
}
//不同包中
package com.lvamber.lah;
import com.lvamber.A;
public class C extends A {
public void access() {
a = 1;
b = 1;
//不同的包,子類不能繼承父類中定義的默認的和
//private的屬性
//c = 1;
//d = 1;
a();
b();
//不同的包,子類不能繼承父類中定義的默認的和
//private的方法
//c();
//d();
}
}
構造器
儘管子類不會繼承父類的任何構造器,但是,子類會在構造器中首先調用父類的構造器。而父類也會在其構造器中調用其自己父類的構造器。直到調用到Object類的構造器爲止。
父類構造器的調用:
子類通過super來調用父類的構造器。當我們在子類的構造器
中沒有顯式的使用super來調用父類的構造器時,編譯器會自動
爲我們補上super()來調用父類無參的構造器。
注意:
當沒有聲明構造器時,編譯器會補充默認的的構造器。同時,在默認的構造器中,會使用super來調用父類無參的構造器。
子類調用父類構造器的語法要求:
1 需要通過super調用父類的構造器,而不能通過父類構造器的名字調用。
2 調用父類的構造器必須出現在子類的構造器中,而不能出現在子類的構造器之外。
3 調用父類的構造器必須出現在子類構造器中的第一條語句。
補充說明:(編譯器補充super)
當在子類構造器中使用this調用子類其他構造器時,編譯器此時不會再補充super來調用父類的無參構造器。(爲了避免重複的初始化)
public class Super {
public static void main(String[] args) {
//new Sub();
}
}
class Super {
//父類構造器就在子類構造器執行之前得到執行。
//子類構造器中會首先調用父類的構造器。
/*public Super() {
System.out.println("父類構造器執行");
}*/
public Super(int x) {
}
}
class Sub extends Super {
/*public Sub() {
//super();
//顯式調用父類含有參數的構造器。
super(10);
System.out.println("子類構造器執行");
}*/
/*
//默認的構造器
public Sub() {
this(3);
super();
}
*/
}
super的使用
1 調用父類的構造器
2 通過super可以訪問父類的成員
public class SuperUse {
public static void main(String[] args) {
Sub1 s = new Sub1();
s.f();
}
}
class Super1 {
public void f() {
System.out.println("父類的f()方法");
}
}
class Sub1 extends Super1 {
public Sub1() {
//調用父類的構造器
super();
//調用當前類的方法
this.f();
//調用父類的f方法。
super.f();
}
public void f() {
super.f();
}
}