在Java中多態(tài)作為面向?qū)ο蟮娜筇匦灾唬匀皇菢O為重要的一個知識內(nèi)容。下面,我將為大家詳細(xì)地介紹關(guān)于Java面向?qū)ο笾卸鄳B(tài)的優(yōu)點(diǎn)。
1.向上轉(zhuǎn)型。
之前繼承有提到過。父類引用指向子類對象。這時的引用只能調(diào)用子類覆蓋重寫了的方法,不能調(diào)用子類特有方法。自動轉(zhuǎn)換
public class Main {
public static void main(String[]args) {
Father f = new Son();
f.money();
}
}
class Father{
void money() {
System.out.println("父類的錢");
}
}
class Son extends Father{
void money() {
System.out.println("子類的錢");
}
void SonPlay() {
System.out.println("爸爸我能打游戲嗎?");
}
}
運(yùn)行結(jié)果:
假如我要該引用區(qū)調(diào)用子類特有的方法(不是覆蓋重寫)呢? 會報錯 (下面的向下轉(zhuǎn)型就是解決這個問題)
下面舉個例子
不同語言輸出"HelloWorld"
(1)父類為正常類
public class Language{ //編程語言類
void HelloWorld() { //輸出HelloWorld
}
}
public class CLanguage extends Language{ //C語言類繼承編程語言類
void HelloWorld() { //輸出HelloWorld
System.out.println("printf("HelloWorld!");");
}
}
public class JavaLanguage extends Language{ //Java繼承編程語言類
void HelloWorld(){
System.out.println("System.out.println("HelloWorld!")");
}
}
提供一個函數(shù)調(diào)用
public class Test {
public static void main(String[]args) {
//inputHelloWorld(new CLanguage());
//inputHelloWorld(new JavaLanguage());
//或者
Language language;
language = new CLanguage();
inputHelloWorld(language);
language = new JavaLanguage();
inputHelloWorld(language);
}
public static void inputHelloWorld(Language language) {
language.HelloWorld();
}
}
在不改變函數(shù)的形參(父類)下,實(shí)參(子類)的改變不會讓程序報錯。也就是說,我只需要關(guān)心的是函數(shù)的形參是與Language類相關(guān)的類(本身或者子類對象)就行,而無需考慮傳入的實(shí)參到底是哪個子類對象。
運(yùn)行結(jié)果:
假如父類是接口或者是抽象類呢?也可以
(2)父類為接口
假如父類真的就是為了提供某標(biāo)準(zhǔn),或者父類無需實(shí)現(xiàn)內(nèi)容等情況,可以考慮吧父類變成接口,接口也支持多態(tài)。
public class Test {
public static void main(String[]args) {
//inputHelloWorld(new CLanguage());
//inputHelloWorld(new JavaLanguage());
//或者
Language language;
language = new CLanguage();
inputHelloWorld(language);
language = new JavaLanguage();
inputHelloWorld(language);
}
public static void inputHelloWorld(Language language) {
language.HelloWorld();
}
}
interface Language{ //編程語言類
public void HelloWorld() ; //輸出HelloWorld
}
class CLanguage implements Language{ //C語言類繼承編程語言類
public void HelloWorld() { //輸出HelloWorld
System.out.println("printf("HelloWorld!");");
}
}
class JavaLanguage implements Language{
public void HelloWorld(){
System.out.println("System.out.println("HelloWorld!")");
}
}
運(yùn)行結(jié)果:
當(dāng)然,抽象類作為父類也可以實(shí)現(xiàn)多態(tài)哦。
2.向下轉(zhuǎn)型。
把父類引用指向子類對象的引用在強(qiáng)轉(zhuǎn)為不同子類對象。 轉(zhuǎn)完之后的對象可以調(diào)用子類特有方法
(解決上述的調(diào)用子類的特有方法會報錯)
public class Main {
public static void main(String[]args) {
Father f = new Son();
//f.money();
Son s = (Son)f;
s.SonPlay();
}
}
class Father{
void money() {
System.out.println("父類的錢");
}
}
class Son extends Father{
void money() {
System.out.println("子類的錢");
}
void SonPlay() {
System.out.println("爸爸我能打游戲嗎?");
}
}
運(yùn)行結(jié)果:
在舉上面的編程語言輸出HelloWorld例子,假如我要求inputLanguage方法對于傳入的實(shí)參中的子類對象進(jìn)行判斷,假如傳入的對象是C語言類就輸出新增的特有的方法,Java類也是一樣
這里就有點(diǎn)像簡單工廠模式(實(shí)參是啥我new啥)了,這里是實(shí)參是啥,我強(qiáng)轉(zhuǎn)之后,我調(diào)用對應(yīng)的方法。
public class CLanguage implements Language{ //C語言類繼承編程語言類
public void HelloWorld() { //輸出HelloWorld
System.out.println("printf("HelloWorld!");");
}
public void CReadMe() { //新增C語言子類特有方法
System.out.println("我是C語言");
}
}
public class JavaLanguage implements Language{
public void HelloWorld(){
System.out.println("System.out.println("HelloWorld!")");
}
public void JavaReadMe() {//新增Java子類特有方法
System.out.println("我是Java");
}
}
修改inputHelloWorld函數(shù)
public class Test {
public static void main(String[]args) {
//inputHelloWorld(new CLanguage());
//inputHelloWorld(new JavaLanguage());
//或者
Language language;
language = new CLanguage();
inputHelloWorld(language);
language = new JavaLanguage();
inputHelloWorld(language);
}
public static void inputHelloWorld(Language language) {
if(language instanceof CLanguage) {
CLanguage clanguage = (CLanguage) language;
clanguage.CReadMe();
}else if(language instanceof JavaLanguage) {
JavaLanguage javalanguage = (JavaLanguage)language;
javalanguage.JavaReadMe();
}
language.HelloWorld();
}
}
運(yùn)行結(jié)果:
總得來說,多態(tài)可以使函數(shù)在其父類形參不變下,實(shí)參可以傳入多個不同的子類對象。