1.多態性
1.概念
向上轉型(自動完成)
子類轉變成父類
父類 父類對象 = 子類實例化對象
向下轉型(強制)
父類轉變成子類,必須首先進行向上轉型
子類 子類對象 = (子類)父類實例化對象
2.子類對象向上轉型
//本程序是多態性的測試
class A //定義類A
{
public void fun1() //定義類A的fun1方法
{
System.out.println("這是類A的fun1方法");
}
public void fun2()
{
this.fun1();
}
}
class B extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類B覆寫的fun1方法");
}
public void fun3()
{
System.out.println("這是類B的fun3方法");
}
}
public class TestPol
{
public static void main(String[] args)
{
B b = new B(); //定義子類的實例化對象
A a = b; //子類對象向上轉型
a.fun1(); //此方法被子類覆寫了,輸出的是覆寫的
a.fun2(); //此方法被子類覆寫了,輸出的是覆寫的
}
}
說明:向上轉型使用方法都是子類覆寫過的方法。
注意:在A中只能看到兩個方法,在B看到三個方法,轉型之後,因爲操作的是父類,所以無法找到子類中定義的新方法。
//本程序是多態性的測試
class A //定義類A
{
public void fun1() //定義類A的fun1方法
{
System.out.println("這是類A的fun1方法");
}
public void fun2()
{
this.fun1();
}
}
class B extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類B覆寫的fun1方法");
}
public void fun3()
{
System.out.println("這是類B的fun3方法");
}
}
public class TestPol
{
public static void main(String[] args)
{
B b = new B(); //定義子類的實例化對象
A a = b; //子類對象向上轉型
a.fun1(); //此方法被子類覆寫了,輸出的是覆寫的
a.fun3(); //新方法
}
}
錯誤信息提示:
TestPol.java:31: 錯誤: 找不到符號 a.fun3(); //新方法 ^ 符號: 方法 fun3() 位置: 類型爲A的變量 a |
3.父類對象向下轉型
//本程序是多態性的測試
class A //定義類A
{
public void fun1() //定義類A的fun1方法
{
System.out.println("這是類A的fun1方法");
}
public void fun2()
{
this.fun1();
}
}
class B extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類B覆寫的fun1方法");
}
public void fun3()
{
System.out.println("這是類B的fun3方法");
}
}
public class TestPol
{
public static void main(String[] args)
{
B b = new B(); //定義子類的實例化對象
A a = b; //子類對象向上轉型
B c = (B) a; //父類向下轉型
c.fun1(); //此方法被子類覆寫了,輸出的是覆寫的
c.fun2(); //新方法
}
}
在類B中存在三個方法,全部可以調用。
注意:進行向下轉型操作時,
//本程序是多態性的測試
class A //定義類A
{
public void fun1() //定義類A的fun1方法
{
System.out.println("這是類A的fun1方法");
}
public void fun2()
{
this.fun1();
}
}
class B extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類B覆寫的fun1方法");
}
public void fun3()
{
System.out.println("這是類B的fun3方法");
}
}
public class TestPol
{
public static void main(String[] args)
{
//B b = new B(); //定義子類的實例化對象
//A a = b; //子類對象向上轉型
A a = new A(); //定義父類的實例化對象
B c = (B) a; //父類向下轉型
c.fun1(); //此方法被子類覆寫了,輸出的是覆寫的
c.fun2(); //新方法
}
}
如果不先進行向上操作的話,會有錯誤信息。
Exception in thread "main" java.lang.ClassCastException: A cannot be cast to B at TestPol.main(TestPol.java:31) |
4.對象多態性的應用
要求設計一個方法,能夠調用A類任意子類的對象。
//本程序是多態性的測試
class A //定義類A
{
public void fun1() //定義類A的fun1方法
{
System.out.println("這是類A的fun1方法");
}
public void fun2()
{
this.fun1();
}
}
class B extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類B覆寫的fun1方法");
}
public void fun3()
{
System.out.println("這是類B的fun3方法");
}
}
class C extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類C覆寫的fun1方法");
}
public void fun4()
{
System.out.println("這是類C的fun4方法");
}
}
public class TestPol
{
public static void main(String[] args)
{
fun(new B());
fun(new C());
}
public static void fun(B b)
{
b.fun1();
}
public static void fun(C c)
{
c.fun1();
}
}
如果子類過多,無法完成這一目標,可以使用對象多態行完成。
//本程序是多態性的測試
class A //定義類A
{
public void fun1() //定義類A的fun1方法
{
System.out.println("這是類A的fun1方法");
}
public void fun2()
{
this.fun1();
}
}
class B extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類B覆寫的fun1方法");
}
public void fun3()
{
System.out.println("這是類B的fun3方法");
}
}
class C extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類C覆寫的fun1方法");
}
public void fun4()
{
System.out.println("這是類C的fun4方法");
}
}
public class TestPol
{
public static void main(String[] args)
{
fun(new B());
fun(new C());
}
public static void fun(A a)
{
a.fun1();
}
}
2.instanceof 關鍵字
在對象轉型中經常使用
1.概念
在java中使用instanceof判斷一個對象到底是哪個類的實。
對象 instanceof 類 ---------------->他返回的是boolean型
//本程序是isntanceof的測試
class A //定義類A
{
public void fun1() //定義類A的fun1方法
{
System.out.println("這是類A的fun1方法");
}
public void fun2()
{
this.fun1();
}
}
class B extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類B覆寫的fun1方法");
}
public void fun3()
{
System.out.println("這是類B的fun3方法");
}
}
public class TestInstanceOf
{
public static void main(String[] args)
{
B b = new B(); //定義子類的實例化對象
A a = b; //向上轉型
A a2 = new A();
System.out.println(a instanceof A);
System.out.println(a instanceof B);
System.out.println(a2 instanceof A);
System.out.println(a2 instanceof B);
}
}
1.作用
如果傳入的是B類的實例,調用fun3,如果是C類調用fun4
//本程序是isntanceof的測試
class A //定義類A
{
public void fun1() //定義類A的fun1方法
{
System.out.println("這是類A的fun1方法");
}
public void fun2()
{
this.fun1();
}
}
class B extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類B覆寫的fun1方法");
}
public void fun3()
{
System.out.println("這是類B的fun3方法");
}
}
class C extends A //類B繼承類A
{
public void fun1() //覆寫fun1方法
{
System.out.println("這是類C覆寫的fun1方法");
}
public void fun4()
{
System.out.println("這是類C的fun4方法");
}
}
public class TestInstanceOf
{
public static void main(String[] args)
{
fun(new B());
fun(new C());
}
public static void fun(A a)
{
if (a instanceof B)
{
A a1 = a; //現在a是子類,先進行向上轉換
B b = (B) a1; //父類向下轉換
b.fun3();
}
if (a instanceof C)
{
A a1 = a; //現在a是子類,先進行向上轉換
C c = (C) a1; //父類向下轉換
c.fun4();
}
}
}
注意:開發中,向下轉型操作要進行驗證,確保不會出問題。
如果要增加新的子類,則要修改fun方法,這樣程序就失去了靈活性。所以程序設計重點放在父類上。只要足夠合理,開發非常方便。
一個類永遠不要去繼承已經實現好了的類,只能繼承抽象類或實現接口。