多態的體現 父類的引用指向了自己的子類對象。 父類的引用也可以接受自己的子類對象。 代碼體現 運行結果 多態的前提 必須是類與類之間有關係。要麼是繼承關係,要麼實現。 存在覆寫關係。 多態利弊 利處 多態的出現大大地提高了程式的拓展性。 弊端 提高了拓展性,但是只能使用父類的引用訪問父類中的成員,不 ...
多態的體現
父類的引用指向了自己的子類對象。
父類的引用也可以接受自己的子類對象。
代碼體現
abstract class Animal {
public abstract void eat();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("eat fish");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("eat bone");
}
}
class Monkey extends Animal {
@Override
public void eat() {
System.out.println("eat banana");
}
}
public class Demo {
public static void main(String[] args) {
/*
Animal c = new Cat();
function(c);
*/
function(new Cat());
/*
Animal d = new Dog();
function(d);
*/
function(new Dog());
/*
Animal m = new Monkey();
function(m);
*/
function(new Monkey());
}
public static void function(Animal a) {
a.eat();
}
}
運行結果
eat fish
eat bone
eat banana
多態的前提
必須是類與類之間有關係。要麼是繼承關係,要麼實現。
存在覆寫關係。
多態利弊
利處
多態的出現大大地提高了程式的拓展性。
弊端
提高了拓展性,但是只能使用父類的引用訪問父類中的成員,不能預先訪問子類的成員(因為子類這時還不存在)。
多態-示例
abstract class Student {
public void eat() {
System.out.println("eat rice");
}
public abstract void study();
}
class StudentToDo {
public void Do(Student s) {
s.eat();
s.study();
}
}
class StudentClass1 extends Student {
@Override
public void eat() {
System.out.println("eat steak");
}
@Override
public void study() {
System.out.println("study English");
}
}
class StudentClass2 extends Student {
@Override
public void study() {
System.out.println("study Chinese");
}
}
class StudentClass3 extends Student {
@Override
public void study() {
System.out.println("study Japanese");
}
}
public class Demo2 {
public static void main(String[] args) {
StudentToDo std = new StudentToDo();
std.Do(new StudentClass1());
std.Do(new StudentClass2());
std.Do(new StudentClass3());
}
}
運行結果:
eat steak
study English
eat rice
study Chinese
eat rice
study Japanese
多態的出現 代碼中的特點(多態使用的註意事項)
多態中成員函數的特點
在編譯時期,參閱引用類型變數所屬的類中是否有調用的方法,如果有編譯通過,如果沒有編譯失敗。
在運行時期,參閱對象所屬的類中是否有調用的方法。
簡單總結:成員函數在多態調用時,編譯看左邊,運行看右邊。
class Fu {
void method1() {
System.out.println("Fu_Method_1");
}
void method2() {
System.out.println("Fu_Method_2");
}
}
class Zi extends Fu {
@Override
void method1() {
System.out.println("Zi_Method_1");
}
void method3() {
System.out.println("Zi_Method_3");
}
}
public class Demo3 {
public static void main(String[] args) {
Fu f =new Zi();
f.method1();
f.method2();
//f.method3(); 對於引用類型f所屬的類Fu中沒有method3()方法,所以編譯會不通過。
}
}
運行結果:
Zi_Method_1
Fu_Method_2
多態中成員變數的特點
無論編譯還是運行,都參考左邊(引用型變數所屬的類)
class Fu {
int num = 1;
}
class Zi extends Fu {
int num = 2;
}
public class Demo4 {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num); //參考左邊
Zi z= new Zi();
System.out.println(z.num);
}
}
運行結果:
1
2
多態中靜態成員函數(變數)的特點
無論編譯還是運行,都參考左邊。
靜態類型,靜態綁定。
非靜態類型,動態綁定。
class Fu {
static void method1() {
System.out.println("Fu_Method_1");
}
}
class Zi extends Fu {
static void method1() {
System.out.println("Zi_Method_1");
}
}
public class Demo5 {
public static void main(String[] args) {
Fu f = new Zi();
f.method1();
Zi z = new Zi();
z.method1();
}
}
運行結果:
Fu_Method_1
Zi_Method_1
多態-轉型
abstract class Animal {
public abstract void eat();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("eat fish");
}
public void CatchMouse() {
System.out.println("CatchMouse");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("eat bone");
}
public void GuardHouse() {
System.out.println("GuardHouse");
}
}
class Monkey extends Animal {
@Override
public void eat() {
System.out.println("eat banana");
}
public void PlayBall() {
System.out.println("Play Ball");
}
}
public class Demo1 {
public static void main(String[] args) {
function(new Cat());
function(new Dog());
function(new Monkey());
}
public static void function(Animal a) {
a.eat();
if (a instanceof Cat) { //instanceof關鍵字用於判斷所屬類型
Cat c = (Cat)a; //向下轉型
c.CatchMouse();
} else if (a instanceof Dog) {
Dog d = (Dog)a; //向下轉型
d.GuardHouse();
} else {
Monkey m = (Monkey)a;//向下轉型
m.PlayBall();
}
}
}
運行結果:
eat fish
CatchMouse
eat bone
GuardHouse
eat banana
Play Ball
多態的應用
以電腦主板為例的示例
分析電腦主板要考慮到拓展性,使用了pci介面,板卡(音效卡,網卡等)和主板都遵循pci介面。
interface Pci {
public void open();
public void close();
}
class MainBoard {
public void run() {
System.out.println("Main Board run");
}
public void usePci(Pci p){ //介面類型指向自己的子類對象
if(p != null){ //加入判斷防止空指針
p.open();
p.close();
}
}
}
class Netcard implements Pci {
@Override
public void open() {
System.out.println("Netcard open");
}
@Override
public void close() {
System.out.println("Netcard close");
}
}
class Soundcard implements Pci {
@Override
public void open() {
System.out.println("Soundcard open");
}
@Override
public void close() {
System.out.println("Soundcard close");
}
}
public class Demo6 {
public static void main(String[] args) {
MainBoard mb = new MainBoard();
mb.run();
mb.usePci(null);
mb.usePci(new Netcard());
mb.usePci(new Soundcard());
}
}
運行結果
Main Board run
Netcard open
Netcard close
Soundcard open
Soundcard close