運(yùn)行時(shí)多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)代碼重用的一個(gè)最強(qiáng)大機(jī)制,動(dòng)態(tài)性的概念也可以被說成
“
一個(gè)接口,多個(gè)方法
”
。
Java
實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)性的基礎(chǔ)是動(dòng)態(tài)方法調(diào)度,它是一種在運(yùn)行時(shí)而不是在編譯期調(diào)用重載方法的機(jī)制,下面就繼承和接口實(shí)現(xiàn)兩方面談?wù)?/span>
java
運(yùn)行時(shí)多態(tài)性的實(shí)現(xiàn)。
一、通過繼承中超類對象引用變量引用子類對象來實(shí)現(xiàn)
舉例說明:
//
定義超類
superA
class superA
{
int i = 100;
void fun()
{
System.out.println(“This is superA”);
}
}
//
定義
superA
的子類
subB
class subB extends superA
{
int m = 1;
void fun()
{
System.out.println(“This is subB”);
}
}
//
定義
superA
的子類
subC
class subC extends superA
{
int n = 1;
void fun()
{
System.out.println(“This is subC”);
}
}
class Test
{
public static void main(String[] args)
{
superA a;
subB b = new subB();
subC c = new subC();
a=b;
a.fun(); (1)
a=c;
a.fun(); (2)
}
}
運(yùn)行結(jié)果為:
This is subB
This is subC
上述代碼中
subB
和
subC
是超類
superA
的子類,我們在類
Test
中聲明了
3
個(gè)引用變量
a, b, c
,通過將子類對象引用賦值給超類對象引用變量來實(shí)現(xiàn)動(dòng)態(tài)方法調(diào)用。也許有人會(huì)問:
“
為什么
(1)
和
(2)
不輸出:
This is superA”
。
java
的這種機(jī)制遵循一個(gè)原則:當(dāng)超類對象引用變量引用子類對象時(shí),被引用對象的類型而不是引用變量的類型決定了調(diào)用誰的成員方法,但是這個(gè)被調(diào)用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。
所以,不要被上例中
(1)
和
(2)
所迷惑,雖然寫成
a.fun()
,但是由于
(1)
中的
a
被
b
賦值,指向了子類
subB
的一個(gè)實(shí)例,因而
(1)
所調(diào)用的
fun()
實(shí)際上是子類
subB
的成員方法
fun()
,它覆蓋了超類
superA
的成員方法
fun()
;同樣
(2)
調(diào)用的是子類
subC
的成員方法
fun()
。
另外,如果子類繼承的超類是一個(gè)抽象類,雖然抽象類不能通過
new
操作符實(shí)例化,但是可以創(chuàng)建抽象類的對象引用指向子類對象,以實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)性。具體的實(shí)現(xiàn)方法同上例。
不過,抽象類的子類必須覆蓋實(shí)現(xiàn)超類中的所有的抽象方法,否則子類必須被
abstract
修飾符修飾,當(dāng)然也就不能被實(shí)例化了。
二、通過接口類型變量引用實(shí)現(xiàn)接口的類的對象來實(shí)現(xiàn)
接口的靈活性就在于
“
規(guī)定一個(gè)類必須做什么,而不管你如何做
”
。我們可以定義一個(gè)接口類型的引用變量來引用實(shí)現(xiàn)接口的類的實(shí)例,當(dāng)這個(gè)引用調(diào)用方法時(shí),它會(huì)根據(jù)實(shí)際引用的類的實(shí)例來判斷具體調(diào)用哪個(gè)方法,這和上述的超類對象引用訪問子類對象的機(jī)制相似。
舉例說明:
//
定義接口
InterA
interface InterA
{
void fun();
}
//
實(shí)現(xiàn)接口
InterA
的類
B
class B implements InterA
{
public void fun()
{
System.out.println(“This is B”);
}
}
//
實(shí)現(xiàn)接口
InterA
的類
C
class C implements InterA
{
public void fun()
{
System.out.println(“This is C”);
}
}
class Test
{
public static void main(String[] args)
{
InterA a;
a= new B();
a.fun();
a = new C();
a.fun();
}
}
輸出結(jié)果為:
This is B
This is C
上例中類
B
和類
C
是實(shí)現(xiàn)接口
InterA
的兩個(gè)類,分別實(shí)現(xiàn)了接口的方法
fun()
,通過將類
B
和類
C
的實(shí)例賦給接口引用
a
而實(shí)現(xiàn)了方法在運(yùn)行時(shí)的動(dòng)態(tài)綁定,充分利用了
“
一個(gè)接口,多個(gè)方法
”
展示了
Java
的動(dòng)態(tài)多態(tài)性。
需要注意的一點(diǎn)是:
Java
在利用接口變量調(diào)用其實(shí)現(xiàn)類的對象的方法時(shí),該方法必須已經(jīng)在接口中被聲明,而且在接口的實(shí)現(xiàn)類中該實(shí)現(xiàn)方法的類型和參數(shù)必須與接口中所定義的精確匹配。
結(jié)束語:以上就是
java
運(yùn)行時(shí)多態(tài)性的實(shí)現(xiàn)方法,大家在編程過程中可以靈活運(yùn)用,但是在性能要求較高的代碼中不提倡運(yùn)用運(yùn)行時(shí)多態(tài),畢竟
Java
的運(yùn)行時(shí)動(dòng)態(tài)方法調(diào)用較之普通的方法調(diào)用的系統(tǒng)開銷是比較大的。