day12 面向對象(下)

day12 面向對象(下) PQ

1、三大特性之多態(polymorphism)

一、多態的簡介

(1)概念

​ 單態:這個對象只有惟一的一種狀態java

​ Student s = new Student();數組

​ 多態:這個對象存在多種狀態。 是指同一行爲,具備多個不一樣表現形式。ide

(2)多態實現的前提

​ 1)要有繼承或者實現的關係測試

​ 2)方法的重寫(若是沒有方法重寫,格式不會報錯,這樣的多態是沒有任何意義)ui

​ 3)父類的引用指向子類對象(父new子)或者父接口的引用指向實現類對象(父接口new實現類)this

二、多態的體現

(1)多態體現的格式

父類類型 變量名 = new 子類對象();
變量名.方法名();

eg:
Animal dog = new Dog();
dog.eat();

(2)多態思想下成員的特色

1)實例變量

​ 對象被什麼數據類型所修飾,這個變量就會調用誰的實例變量code

//父類:SuperClass
public class SuperClass {
	int num = 10;
}
//子類:SubClass
public class SubClass extends SuperClass {
	int num = 20;
}
//測試類:PolyDemo02
public class PolyDemo02 {
	public static void main(String[] args) {
		//父new父
		SuperClass superC = new SuperClass();
		System.out.println(superC.num);//10
		//子new子
		SubClass subC = new SubClass();
		System.out.println(subC.num);//20
		System.out.println("===================");
		//利用多態建立對象
		SuperClass sc = new SubClass();
		System.out.println(sc);//com.atguigu.poly.demo02.SubClass@15db9742 子類地址值
		System.out.println(sc.num);//10
	}
}
2)實例方法

​ 先看父類中是否有這個方法,若是有,執行子類重寫後的方法;若是沒有,編譯報錯對象

//父類:SuperClass
public class SuperClass {
	public void method () {
		System.out.println("父類的實例方法");
	}
}
//子類:SubClass
public class SubClass extends SuperClass {
	public void method () {
		System.out.println("子類重寫後的實例方法");
	}
}
//測試類:PolyDemo04
public class PolyDemo04 {
	public static void main(String[] args) {
		//父new父
		SuperClass superC = new SuperClass();
		System.out.println(superC);  //com.atguigu.poly.demo04.SuperClass@15db9742
		superC.method();//父類的實例方法
		System.out.println("==============");
		//子new子
		SubClass subC = new SubClass();
		System.out.println(subC);//com.atguigu.poly.demo04.SubClass@6d06d69c
		subC.method();//父類的實例方法
		System.out.println("==============");
		//父new子
		SuperClass sc = new SubClass();
		System.out.println(sc);//com.atguigu.poly.demo04.SubClass@7852e922
		sc.method();//父類的實例方法
	}
}
3)構造器

​ 和原來同樣繼承

//父類:SuperClass
public class SuperClass {
	
	public SuperClass () {
		System.out.println("父類的構造器");
	}
}
//子類:SubClass
public class SubClass extends SuperClass {
	
	public SubClass(){
		//super(); 此處隱藏了JVM提供的super()
		System.out.println("子類的構造器");
	}
}
//測試類PolyDemo03
public class PolyDemo03 {
	public static void main(String[] args) {
		//父new父
		SuperClass superC = new SuperClass();//父類的構造器
		System.out.println("================");
		//子new子
		SubClass subC = new SubClass();//父類的構造器      子類的構造器
		System.out.println("================");
		// 父new子
		SuperClass sc = new SubClass();//父類的構造器      子類的構造器
		System.out.println(sc);	//com.atguigu.poly.demo03.SubClass@15db9742	
	}
}

三、多態的好處和弊端

(1)多態的好處

  • 聲明方法時,再也不將形參寫具體的引用數據類型,直接寫父類的類型或者父類接口的類型
  • 對象數組的應用
//Student類
public class Student {
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
    //設置滿參構造器
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	//重寫系統中自帶的toString方法
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}	
}
//測試類:PolyDemo05
public class PolyDemo05 {
	public static void main(String[] args) {
		Student s1 = new Student("張三",18);
		Student s2 = new Student("李四",23);
		Student s3 = new Student("錢五",43);
		Student s4 = new Student("孫六",23);
		//對象數組
		Student[] arr = {s1,s2,s3,s4};
		
		printArr(arr);
	}
	//object爲頂級父類,將其放置形參
	private static void printArr(Object[] arr) { 
		for (int i = 0; i < arr.length; i++) {
			Object obj = arr[i];
			System.out.println(obj);
		}
	}
}
//運行結果
Student [name=張三, age=18]
Student [name=李四, age=23]
Student [name=錢五, age=43]
Student [name=孫六, age=23]

(2)多態的弊端及解決辦法

1)多態的弊端

​ 在多態的狀況下,對象沒法調用本身的特有方法,只能調用子類改寫父類的方法。接口

2)多態的解決方法

​ 解決多態的弊端,引用數據類型的類型轉換

類型轉換名稱 類型轉換方向
向上轉型(默認轉換方式) 將子類的對象或者實現類的對象轉換爲父類的類型或者父接口類型(多態)
向下轉型(強制類型轉換) 將父類類型或者父接口類型轉換爲子類類型或者實現類類型
  • 向下轉型(強制類型轉換)格式:
子類類型   對象名 = (子類類型)父類類型的對象;
eg:
Animal cat = new Cat();  //多態
Dog dog = (Dog)cat;      //強轉
  • 引用數據類型強制類型轉換時注意事項:

    可能會發生ClassCastException:類型轉換異常

3)instanceof關鍵字的引入

​ 強制轉換時易發生類型轉換異常,使用instanceof給引用變量作類型的校驗

  • instanceof使用格式
變量名 instanceof 數據類型 

eg:
c instanceof Cat
  • instanceof返回值

    instanceof爲關係運算符,若是變量屬於該數據類型,返回true;若是變量不屬於該數據類型,返回false。

四、練習題:貓狗

1.定義動物類
		屬性:年齡,顏色
		行爲:eat(String something)方法(無具體行爲,不一樣動物吃的方式和東西不同,
			something表示吃的東西)生成空參有參構造,set和get方法
	2.定義狗類繼承動物類	  
		行爲:eat(String something)方法,看家lookHome方法(無參數)
	3.定義貓類繼承動物類
		行爲:eat(String something)方法,逮老鼠catchMouse方法(無參數)
	4.定義Person類
		屬性:姓名,年齡
		行爲:keepPet(Dog dog,String something)方法
		功能:餵養寵物狗,something表示餵養的東西
		行爲:keepPet(Cat cat,String something)方法
		功能:餵養寵物貓,something表示餵養的東西
		實現以上兩種行爲,思考如何只寫一個方法?
		生成空參有參構造,set和get方法  	
	5.測試以上方法
	  使用多態、強轉、instanceof等
//Animal類
public abstract class Animal {
	private int age;
	private String color;
    //設置set()、get()方法
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	//設置無參構造器和滿參構造器
	public Animal(int age, String color) {
		super();
		this.age = age;
		this.color = color;
	}
	public Animal() {
		super();
	}
	//設置動物類的抽象方法
	public abstract void eat(String something);
}
//Cat類 繼承 Animal類
public class Cat extends Animal{
	//重寫父類eat方法
	public void eat(String something) {
		System.out.println(getAge() + "歲" + getColor() + "色的小貓正在吃" + something);
	}
	//逮老鼠方法
	public void catchMouse () {
		System.out.println(getAge() + "歲" + getColor() + "色的小貓正在逮老鼠");
	}
	//設置構造器
	public Cat() {
		super();
	}

	public Cat(int age, String color) {
		super(age, color);
	}
}
//Dog類 繼承 Animal類
public class Dog extends Animal{
	//重寫父類抽象方法
	@Override
	public void eat(String something) {
		System.out.println(getAge() + "歲" + getColor() + "色的小狗正在吃" + something);
	}
	
	public void lookHome(){
		System.out.println(getAge() + "歲" + getColor() + "色的小狗正在看家");
	}
	//設置構造器
	public Dog() {
		super();
	}

	public Dog(int age, String color) {
		super(age, color);
	}	
}
//Person類
public class Person {
	//餵養狗和餵養貓的方法爲方法的重載,能夠直接使用多態的好處一:聲明方法時,再也不將形參寫具體的引用數據類型,直接寫父類的類型或者父類接口的類型
	/*// 餵養狗的方法
	public void keepPet(Dog dog,String something) {
		dog.eat(something);
	}
	
	// 餵養貓的方法
	public void keepPet(Cat cat,String something) {
		cat.eat(something);
	}*/
	
	public void keepPet (Animal a,String something) {
		a.eat(something);
	}
}
//測試類:
public class PolyDemo06 {
	public static void main(String[] args) {
		//建立貓對象
		Animal cat = new Cat(2,"白");
		//建立狗的對象
		Animal dog = new Dog(3,"黑");
		//建立人對象
		Person p = new Person();
		// 調用飼養員的餵養貓的方法
		p.keepPet(cat, "魚");
		
		// 將多態形式的對象進行向下轉型
		if (cat instanceof Cat) {
			Cat c = (Cat)cat;
			c.catchMouse();
		}
		//cat對象不屬於Dog,判斷返回false
		if (cat instanceof Dog) {
			Dog d = (Dog)cat;
			d.lookHome();
		}
		//Cat c = (Cat)dog;	
		//c.catchMouse();
		System.out.println("==================");
		// 調用飼養員餵養狗的方法
		p.keepPet(dog, "骨頭");
	}
}

2、匿名內部類

相關文章
相關標籤/搜索