繼承
Java使用extends
關鍵字來實現繼承:
class Person {
private String name;
private int age;
public String getName() {...}
public void setName(String name) {...}
public int getAge() {...}
public void setAge(int age) {...}
}
class Student extends Person {
// 不要重複name和age字段/方法,
// 只需要定義新增score字段/方法:
private int score;
public int getScore() {...}
public void setScore(int score) {...}
}
通過繼承,子類Student
獲得了父類Person
已有的字段與方法,節省了重複編寫代碼的時間。
Java中所有的類都繼承自Object
這個類,除了它自身。private
關鍵字修飾的字段,只能在類中被訪問,子類也無法訪問,爲了讓子類也能使用父類的字段,要把修飾符改成protected
。
多態
在上一篇中講到構造方法時有提到過方法簽名的概念,當一個子類與其父類有着相同的方法簽名的方法(修飾符、參數、返回值都相同)時,稱之爲覆寫。
注意上篇中講的重載,並不要求方法簽名完全相同,編譯器也是根據這個將重載的方法區分開來。覆寫則在運行期間動態決定調用的方法,以實現多態。
class Animal {
public void sound {...}
}
class Cat {
@Override
public void sound {
System.out.println("meow")
}
}
使用@Override
可以讓編譯器幫我們檢查覆寫是否正確。
final修飾符:
-
final
修飾的字段必須在聲明是初始化並且無法被修改,也就是常量 -
final
修飾的方法不能被子類覆寫 -
final
修飾的類不能被繼承
抽象類
有時候,如果父類的方法沒有實際意義,能不能不寫呢?
class Person {
public void run(); // Compile Error!
}
上述代碼會報錯。
如果一個方法只定義方法簽名,沒有實質內容,可以用abstract
修飾符把它定義成抽象方法,包含抽象方法的類也必須被聲明爲抽象類(abstract class)。
abstract class Person {
public abstract void run();
}
抽象類不能被實例化,方法也是空的,這個類用來幹什麼的呢?抽象類本身被設計成只能用於被繼承,因此,抽象類可以強迫子類實現其定義的抽象方法,否則編譯會報錯。因此,抽象方法實際上相當於定義了“規範”。
對於抽象類的子類,我們可以用抽象類型去引用它的子類型:
Person s = new Student();
Person t = new Teacher();
s.run();
t.run();
我們可以直接調用它的方法而不必關心具體類型,可以確信抽象類的子類是一定實現了這些方法的。
接口
有一種極端的“抽象類”,它只包含抽象方法,這種東西可以寫成接口。
interface Person {
void run();
String getName();
}
由於接口肯定都是抽象方法了,所以沒必要用abstract
修飾符。事實上它的方法都默認是public abstract
。聲明接口用interface
。
某個類要去實現接口,要用implements
關鍵字。
class Dog implements Animal {
...
}
Java中一個類只能繼承自一個父類,通過接口則可以實現多重繼承,一個類可以實現多個接口。(Python支持多重繼承)
接口中還可以有一種default
修飾符修飾的默認方法,這種方法可以有一個默認實現,具體實現的類可以不必覆寫它。
包
有時候可能兩個人都實現了一個名爲Person
的類,同時還想引用對方的類來使用。對於這種命名衝突的情況應該怎麼辦呢?
Java使用包package
來解決命名衝突。在定義一個類時,把它的包名寫在第一行。
下面是用IDE編寫程序時自動創建的代碼部分:
package com.company;
public class Main {
public static void main(String[] args) {
}
}
與下面某人編寫的同名Main
類:
package harry;
public class Main {
public static void main(String[] args) {
}
}
雖然這兩個類同名了,但在運行時,這兩個類會使用完整類名,它們的完整名分別是com.company.Main
和harry.Main
。
有時候要使用一個包中的類,一種寫法是直接寫完整類名,但那樣就有點麻煩,我們可以和Python
中一樣使用import
語句。
例如要使用 java.util
包中的ArrayList
:
import java.util.ArrayList;
public class SingleImport {
public static void main(String[] args) {
ArrayList list = new ArrayList();
}
}
這個包裏還含有很多類,可以使用星號*
:
import java.util.*;
這樣表示把這個包裏所有類都導入。
掃碼關注: