1. 程式人生 > >第三十一、Java面向物件三大特徵之多型

第三十一、Java面向物件三大特徵之多型

面向物件的三大特徵:

1. 封裝
2. 繼承。
3. 多型


多型:

      一個物件具備多種形態。(父類的引用型別變數指向了子類的物件、或者是介面的引用型別變數指向了介面實現類的物件)

多型的前提:

    必須存在繼承或者實現 關係。
    動物  a  = new   狗();

//動物類
abstract class Animal{

	String name;
	String  color = "動物色";

	public Animal(String name){
		this.name = name;
	}

	public abstract void run();

	public static void eat(){
		System.out.println("動物在吃..");
	}

}

//老鼠
class  Mouse extends Animal{

	String color = "黑色";

	public Mouse(String name){
		super(name);
	}
	
	public  void run(){
		System.out.println(name+"四條腿慢慢的走!");
	}

	public static void eat(){
		System.out.println("老鼠在偷吃..");
	}

	//老鼠特有方法---打洞
	public void dig(){
		System.out.println("老鼠在打洞..");
	}
}



class Fish extends Animal {

	public Fish(String name){
		super(name);
	}
	
	
	public  void run(){
		System.out.println(name+"搖搖尾巴游..");
	}
}


class MyClass 
{
	public static void main(String[] args) 
	{
		/*
		Mouse m = new Mouse("老鼠");
		System.out.println(m.color);//普通的輸出的是子類物件的成員變數
		
		//多型: 父類的引用型別變數指向子類的物件
		*/
		Animal a = new Mouse("老鼠");
                System.out.println(a.color);//多型的情況下 訪問的是誰的呢?父類的成員變數
 
		a.dig();//不能訪問
		//a.eat();//同名的靜態成員函式
	}	
}

多型要注意的細節:

1.  多型情況下,子父類存在同名的(靜態、非靜態)成員變數時,訪問的是父類的成員變數。
2.  多型情況下,子父類存在同名的非靜態的成員函式時,訪問的是子類的成員函式。
3.  多型情況下,子父類存在同名的靜態的成員函式時,訪問的是父類的成員函式。
4.  多型情況下,不能訪問子類特有的成員。

總結:多型情況下,子父類存在同名的成員時,訪問的都是父類的成員,除了在同名非靜態函式時才是訪問子類的。

編譯原理:
編譯看左邊,執行不一定看右邊。
編譯看左邊:java編譯器在編譯的時候,會檢查引用型別變數所屬的類是否具備指定的成員,如果不具備馬上編譯報錯。

多型的應用:

  1. 多型用於形參型別的時候,可以接收更多型別的資料 。
  2. 多型用於返回值型別的時候,可以返回更多型別的資料。

多型的好處: 提高了程式碼的拓展性。


需求1: 定義一個函式可以接收任意型別的圖形物件,並且列印圖形面積與周長。
//圖形類
abstract class MyShape{

	public abstract void getArea();

	public abstract void getLength();	
}

class Circle extends MyShape{

	public static final double PI = 3.14;

	double r;

	public Circle(double r){
		this.r =r ;	
	}

	public  void getArea(){
		System.out.println("圓形的面積:"+ PI*r*r);
	}

	public  void getLength(){
		System.out.println("圓形的周長:"+ 2*PI*r);
	}
}


class Rect  extends MyShape{

	int width;

	int height;

	public Rect(int width , int height){
		this.width = width;
		this.height = height;
	}

	public  void getArea(){
		System.out.println("矩形的面積:"+ width*height);
	}

	public  void getLength(){
		System.out.println("矩形的周長:"+ 2*(width+height));
	}
}

class MyClass {

	public static void main(String[] args) 
	{
		Circle c = new Circle(4.0);
		print(c);

		Rect r = new Rect(3,4);
		print(r);
		

	}


	//需求1: 定義一個函式可以接收任意型別的圖形物件,並且列印圖形面積與周長。
	public static void print(MyShape s){ // MyShpe s = new Circle(4.0);
		s.getArea();
		s.getLength();
	}
}
執行結果如下:

LoveQideMacBook-Pro:desktop loveqi$ java MyClass

圓形的面積:50.24

圓形的周長:25.12

矩形的面積:12

矩形的周長:14

2. 多型用於返回值型別的時候,可以返回更多型別的資料。
//圖形類
abstract class MyShape{

	public abstract void getArea();

	public abstract void getLength();	
}

class Circle extends MyShape{

	public static final double PI = 3.14;

	double r;

	public Circle(double r){
		this.r =r ;	
	}

	public  void getArea(){
		System.out.println("圓形的面積:"+ PI*r*r);
	}

	public  void getLength(){
		System.out.println("圓形的周長:"+ 2*PI*r);
	}
}


class Rect  extends MyShape{

	int width;

	int height;

	public Rect(int width , int height){
		this.width = width;
		this.height = height;
	}

	public  void getArea(){
		System.out.println("矩形的面積:"+ width*height);
	}

	public  void getLength(){
		System.out.println("矩形的周長:"+ 2*(width+height));
	}
}



class MyClass {

	public static void main(String[] args) 
	{
		MyShape m = getShape(0); //呼叫了使用多型的方法,定義的變數型別要與返回值型別一致。
		m.getArea();
		m.getLength();	
	}

       // 需求2: 定義一個函式可以返回任意型別的圖形物件。
	public static MyShape  getShape(int i){
		if (i==0){
			return new Circle(4.0);
		}else{
			return new Rect(3,4);
		}
	}
}

執行結果如下:

LoveQideMacBook-Pro:desktop loveqi$ java MyClass

圓形的面積:50.24

圓形的周長:25.12


多型弊端:  只能使用父類引用指向父類成員

多型情況下,不能訪問子類特有的成員