1. 程式人生 > >11_Java面向物件_第11天(介面、多型)_講義

11_Java面向物件_第11天(介面、多型)_講義

今日內容介紹
1、介面
2、多型
第1章 介面
1.1 介面概念
介面是功能的集合,同樣可看做是一種資料型別,是比抽象類更為抽象的”類”。
介面只描述所應該具備的方法,並沒有具體實現,具體的實現由介面的實現類(相當於介面的子類)來完成。這樣將功能的定義與實現分離,優化了程式設計。
請記住:一切事物均有功能,即一切事物均有介面。
1.2 介面的定義
與定義類的class不同,介面定義時需要使用interface關鍵字。
定義介面所在的仍為.java檔案,雖然宣告時使用的為interface關鍵字的編譯後仍然會產生.class檔案。這點可以讓我們將介面看做是一種只包含了功能宣告的特殊類。
定義格式:

public interface 介面名 {
抽象方法1;
抽象方法2;
抽象方法3;
}

使用interface代替了原來的class,其他步驟與定義類相同:
 介面中的方法均為公共訪問的抽象方法
 介面中無法定義普通的成員變數
1.3 類實現介面
類與介面的關係為實現關係,即類實現介面。實現的動作類似繼承,只是關鍵字不同,實現使用implements。
其他類(實現類)實現介面後,就相當於宣告:”我應該具備這個介面中的功能”。實現類仍然需要重寫方法以實現具體的功能。
格式:

class 類 implements 介面 {
	重寫介面中方法
} 

在類實現介面後,該類就會將介面中的抽象方法繼承過來,此時該類需要重寫該抽象方法,完成具體的邏輯。
 介面中定義功能,當需要具有該功能時,可以讓類實現該介面,只聲明瞭應該具備該方法,是功能的宣告。
 在具體實現類中重寫方法,實現功能,是方法的具體實現。


於是,通過以上兩個動作將功能的宣告與實現便分開了。
(此時請重新思考:類是現實事物的描述,介面是功能的集合。)
1.4 介面中成員的特點
1、介面中可以定義變數,但是變數必須有固定的修飾符修飾,public static final 所以介面中的變數也稱之為常量,其值不能改變。後面我們會講解static與final關鍵字
2、介面中可以定義方法,方法也有固定的修飾符,public abstract
3、介面不可以建立物件。
4、子類必須覆蓋掉介面中所有的抽象方法後,子類才可以例項化。否則子類是一個抽象類。

package cn.itcast.demo01;
/*
 * 定義介面
 * 		使用關鍵字interface 介面名字
 * 介面定義:
 * 		成員方法,全抽象
 * 		不能定義帶有方法體的方法
 * 定義抽象方法:固定格式
 * 
 * 	public abstract 返回值型別   方法名字(引數列表)
 * 修飾符public 寫,或者不寫,都是public
 * 
 * 介面中成員變數的定義
 * 		成員變數的定義,具體要求
 * 
 * 		要求:必須定義為常量
 * 		固定格式:
 * 			public static final 資料型別  變數名 = 值
 */
public interface MyInterface {
	
	public static final int a = 1;
	
	//在介面中,定義抽象的方法
	public abstract void function();
}

package cn.itcast.demo01;
/*
 * 定義類,實現介面,重寫介面中的抽象方法
 * 類實現介面,可以理解為繼承
 * 關鍵字implements
 * class 類implements 介面{
 * 		重寫介面中的抽象方法
 * }
 * 					類				實現		介面
 * public class MyInterfaceImpl implements MyInterface
 */
public class MyInterfaceImpl implements MyInterface{
	public void function(){
		System.out.println("實現類,重寫介面抽象方法");
	}
}

package cn.itcast.demo01;

public class Test {

	public static void main(String[] args) {
		//建立介面的實現類的物件
		MyInterfaceImpl my = new MyInterfaceImpl();	
		my.function();
		System.out.println(my.a);
	}

}

在這裡插入圖片描述

package cn.itcast.demo02;
/*
 * 介面中成員的特點:
 * 		1.成員變數的特點,沒有變數,都是常量
 * 		固定定義格式:public static final 資料型別 變數名 = 值
 * 		public  許可權
 * 		static	可以被類名直接呼叫
 * 		final	最終,固定住變數的值
 * 
 * 注意:public static final 修飾符,在介面的定義中,可以省略不寫
 * 但是,不寫不等於沒有
 * 三個修飾符,還可以選擇性書寫
 * 
 * 2.介面中的成員方法特點:
 * 		public abstract 返回值型別   方法名(引數列表)
 * 		修飾符public abstract 可以不寫,選擇性書寫
 * 		但是,寫不寫,都有
 * 
 * 3.實現類,實現介面,重寫介面全部抽象方法,建立實現類物件
 * 		實現類,重寫一部分抽象方法,實現類,還是一個抽象類
 * 
 * 4.子類必須覆蓋掉介面中所有的抽象方法後,子類才可以例項化。否則子類是一個抽象類
 */
public interface MyInter {
	
	public static final int x = 3;
	
	public abstract void show();
	
	public abstract int getNum();
}

package cn.itcast.demo02;

public abstract class MyInterfaceImpl implements MyInter{
	//重寫介面中的抽象方法,public許可權是必須的
	public void show(){
		System.out.println("show");
	}
}

package cn.itcast.demo02;
/*
 * 
 */
public class Test {

	public static void main(String[] args) {
		//使用介面中定義的常量
		//常量被靜態修飾,可以被類名直接呼叫,被介面的名字直接呼叫
		System.out.println(MyInter.x);//3
		//MyInter.x = 1;//The final field MyInter.x cannot be assigned
		//Cannot instantiate the type MyInterfaceImpl  還是一個抽象類
//		MyInterfaceImpl my = new MyInterfaceImpl();
//		my.show();
	}

}

在這裡插入圖片描述
1.5 介面的多實現
瞭解了介面的特點後,那麼想想為什麼要定義介面,使用抽象類描述也沒有問題,介面到底有啥用呢?
介面最重要的體現:解決多繼承的弊端。將多繼承這種機制在java中通過多實現完成了。

interface Fu1
{
	void show1();
}
interface Fu2
{
	void show2();
}
class Zi implements Fu1,Fu2// 多實現。同時實現多個介面。
{
	public void show1(){}
	public void show2(){}
}

怎麼解決多繼承的弊端呢?
弊端:多繼承時,當多個父類中有相同功能時,子類呼叫會產生不確定性。
其實核心原因就是在於多繼承父類中功能有主體,而導致呼叫執行時,不確定執行哪個主體內容。
為什麼多實現能解決了呢?
因為介面中的功能都沒有方法體,由子類來明確。
在這裡插入圖片描述

package cn.itcast.demo03;

public interface A {
	public abstract void a();
}

package cn.itcast.demo03;

public interface B {
//	public abstract void a();
//	public abstract int a();
	public abstract void b();
}

package cn.itcast.demo03;

public abstract class D {
	public abstract void d();
}

package cn.itcast.demo03;
/*
 * 類C,同時實現2個介面,介面A,B
 * 作為實現類C,全部重寫兩個介面的所有抽象方法,才能建立C類的
 * 
 * C類,在繼承一個類的同時,可以實現多個介面
 */
public class C extends D implements A, B {
//	public void a(){
//		
//	}
	//必須拋棄一個
//	public int a(){
//		
//	}
	public void a(){
		
	}
	
	public void b(){
		
	}

	public void d(){
	
	}
}

1.6 類繼承類同時實現介面
介面和類之間可以通過實現產生關係,同時也學習了類與類之間可以通過繼承產生關係。當一個類已經繼承了一個父類,它又需要擴充套件額外的功能,這時介面就派上用場了。
子類通過繼承父類擴充套件功能,通過繼承擴充套件的功能都是子類應該具備的基礎功能。如果子類想要繼續擴充套件其他類中的功能呢?這時通過實現介面來完成。

class Fu {
	public void show(){}
}
interface Inter {
	pulbic abstract void show1();
}
class Zi extends Fu implements Inter {
	public void show1() {
	}
}

介面的出現避免了單繼承的侷限性。父類中定義的事物的基本功能。介面中定義的事物的擴充套件功能。
1.7 介面的多繼承
學習類的時候,知道類與類之間可以通過繼承產生關係,介面和類之間可以通過實現產生關係,那麼介面與介面之間會有什麼關係。
多個介面之間可以使用extends進行繼承。

interface Fu1{
	void show();
}
interface Fu2{
	void show1();
}
interface Fu3{
	void show2();
}
interface Zi extends Fu1,Fu2,Fu3{
	void show3();
}

package cn.itcast.demo04;

public interface A {
	public abstract void a();
}

package cn.itcast.demo04;

public interface B {
	public abstract void b();
}

package cn.itcast.demo04;
/*
 * 介面與介面之間,是繼承關係
 * Java支援介面之間的f繼承,一個介面可以同時繼承多個介面
 */
public interface C {
	public abstract void c();
}

package cn.itcast.demo04;
/*
 * 實現介面C,重寫C介面的全部抽象方法
 * 而且介面C,繼承A,B
 * D實現類,重寫A,B,C三介面的全部抽象方法
 * 問:Java中有多繼承:
 * 		類是沒有多繼承,只有多層繼承
 * 		介面之間多繼承
 */
public class D implements C{
	public  void a(){
		
	}
	
	public  void b(){
			
	}
	
	public  void c(){
		
	}
}

在開發中如果多個介面中存在相同方法,這時若有個類實現了這些介面,那麼就要實現介面中的方法,由於介面中的方法是抽象方法,子類實現後也不會發生呼叫的不確定性。
1.8 介面的思想
前面學習了介面的程式碼體現,現在來學習介面的思想,接下里從生活中的例子進行說明。
舉例:我們都知道電腦上留有很多個插口,而這些插口可以插入相應的裝置,這些裝置為什麼能插在上面呢?主要原因是這些裝置在生產的時候符合了這個插口的使用規則,否則將無法插入介面中,更無法使用。發現這個插口的出現讓我們使用更多的裝置。
總結:介面在開發中的它好處
1、介面的出現擴充套件了功能。
2、介面其實就是暴漏出來的規則。
3、介面的出現降低了耦合性,即裝置與裝置之間實現瞭解耦。

介面的出現方便後期使用和維護,一方是在使用介面(如電腦),一方在實現介面(插在插口上的裝置)。例如:筆記本使用這個規則(介面),電腦外圍裝置實現這個規則(介面)。
1.9 介面和抽象類的區別
明白了介面思想和介面的用法後,介面和抽象類的區別是什麼呢?介面在生活體現也基本掌握,那在程式中介面是如何體現的呢?
通過例項進行分析和程式碼演示抽象類和介面的用法。
1、舉例:
犬:
行為:
吼叫;
吃飯;
緝毒犬:
行為:
吼叫;
吃飯;
緝毒;
2、思考:
由於犬分為很多種類,他們吼叫和吃飯的方式不一樣,在描述的時候不能具體化,也就是吼叫和吃飯的行為不能明確。當描述行為時,行為的具體動作不能明確,這時,可以將這個行為寫為抽象行為,那麼這個類也就是抽象類。
可是當緝毒犬有其他額外功能時,而這個功能並不在這個事物的體系中。這時可以讓緝毒犬具備犬科自身特點的同時也有其他額外功能,可以將這個額外功能定義介面中。
如下程式碼演示:

interface 緝毒{
	public abstract void 緝毒();
}
//定義犬科的這個提醒的共性功能
abstract class 犬科{
public abstract void 吃飯();
public abstract void 吼叫();
}
// 緝毒犬屬於犬科一種,讓其繼承犬科,獲取的犬科的特性,
//由於緝毒犬具有緝毒功能,那麼它只要實現緝毒介面即可,這樣即保證緝毒犬具備犬科的特性,也擁有了緝毒的功能
class 緝毒犬 extends 犬科 implements 緝毒{

	public void 緝毒() {
	}
	void 吃飯() {
	}
	void 吼叫() {
	}
}
class 緝毒豬 implements 緝毒{
	public void 緝毒() {
	}
}

3、通過上面的例子總結介面和抽象類的區別:
相同點:
 都位於繼承的頂端,用於被其他類實現或繼承;
 都不能直接例項化物件;(不可以new的)
 都包含抽象方法,其子類都必須覆寫這些抽象方法;
區別:
 抽象類為部分方法提供實現,避免子類重複實現這些方法,提高程式碼重用性;介面只能包含抽象方法;
 一個類只能繼承一個直接父類(可能是抽象類),卻可以實現多個介面;(介面彌補了Java的單繼承)
 抽象類是這個事物中應該具備的你內容, 繼承體系是一種 is…a關係
 介面是這個事物中的額外內容,繼承體系是一種 like…a關係
二者的選用:
 優先選用介面,儘量少用抽象類;
 需要定義子類的行為,又要為子類提供共性功能時才選用抽象類;
第2章 多型
2.1 多型概述
多型是繼封裝、繼承之後,面向物件的第三大特性。
現實事物經常會體現出多種形態,如學生,學生是人的一種,則一個具體的同學張三既是學生也是人,即出現兩種形態。
Java作為面向物件的語言,同樣可以描述一個事物的多種形態。如Student類繼承了Person類,一個Student的物件便既是Student,又是Person。
Java中多型的程式碼體現在一個子類物件(實現類物件)既可以給這個子類(實現類物件)引用變數賦值,又可以給這個子類(實現類物件)的父類(介面)變數賦值。
如Student類可以為Person類的子類。那麼一個Student物件既可以賦值給一個Student型別的引用,也可以賦值給一個Person型別的引用。
最終多型體現為父類引用變數可以指向子類物件。
多型的前提是必須有子父類關係或者類實現介面關係,否則無法完成多型。
在使用多型後的父類引用變數呼叫方法時,會呼叫子類重寫後的方法。
2.2 多型的定義與使用格式
多型的定義格式:就是父類的引用變數指向子類物件

父類型別  變數名 = new 子類型別();
變數名.方法名();

 普通類多型定義的格式

父類 變數名 = new 子類();
如:	class Fu {}
	class Zi extends Fu {}
	//類的多型使用
Fu f = new Zi();

 抽象類多型定義的格式

抽象類 變數名 = new 抽象類子類();
如:	abstract class Fu {
         public abstract void method();
	     }
class Zi extends Fu {
public void method(){
		      System.out.println(“重寫父類抽象方法”);
}
}
//類的多型使用
Fu fu= new Zi();

 介面多型定義的格式

介面 變數名 = new 介面實現類();
如: interface Fu {
		     public abstract void method();
}
class Zi implements Fu {
		     public void method(){
              System.out.println(“重寫介面抽象方法”);
}
}
//介面的多型使用
Fu fu = new Zi();
package cn.itcast.demo05;

public class Fu {
	public void show(){
		System.out.println("父類的show方法");
	}
	
}

package cn.itcast.demo05;

public class Zi extends Fu {
	public void show(){
		System.out.println("子類重寫父類的show方法");
	}
}

package cn.itcast.demo05;

public abstract class Animal {
	public abstract void eat();
}

package cn.itcast.demo05;

public class Cat extends Animal {

	@Override
	public void eat() {
		System.out.println("貓吃貓糧");
	}

}

package cn.itcast.demo05;

public interface Smoking {
	public abstract void smoking();
}

package cn.itcast.demo05;

public class Student implements Smoking {

	@Override
	public void smoking() {
		System.out.println("學生抽菸");
	}

}

package cn.itcast.demo05;

public class Test {

	public static void main(String[] args) {
		//多型呼叫方法,方法必須執行子類的重寫
		//Java中,物件的多型性,呼叫程式中的方法
		//公式:父類型別或者是介面型別		變數   = new 子類的物件();
		Fu f = new Zi();
		f.show();
		
		//抽象類Animal,子類Cat
		Animal a = new Cat();
		a.eat();
		
		//介面smoking,實現類Student
		Smoking sk = new Student();
		sk.smoking();
	}

}

在這裡插入圖片描述
 注意事項
同一個父類的方法會被不同的子類重寫。在呼叫方法時,呼叫的為各個子類重寫後的方法。

如 Person p1 = new Student();
   Person p2 = new Teacher();
   p1.work(); //p1會呼叫Student類中重寫的work方法
   p2.work(); //p2會呼叫Teacher類中重寫的work方法

當變數名指向不同的子類物件時,由於每個子類重寫父類方法的內容不同,所以會呼叫不同的方法。
2.3 多型-成員的特點
掌握了多型的基本使用後,那麼多型出現後類的成員有啥變化呢?前面學習繼承時,我們知道子父類之間成員變數有了自己的特定變化,那麼當多型出現後,成員變數在使用上有沒有變化呢?
多型出現後會導致子父類中的成員變數有微弱的變化。看如下程式碼

class Fu {
	int num = 4;
}
class Zi extends Fu {
	int num = 5;
}
class Demo {
	public static void main(String[] args) 	{
		Fu f = new Zi();
		System.out.println(f.num);
		Zi z = new Zi();
		System.out.println(z.num);
	}
}

 多型成員變數
當子父類中出現同名的成員變數時,多型呼叫該變數時:
編譯時期:參考的是引用型變數所屬的類中是否有被呼叫的成員變數。沒有,編譯失敗。
執行時期:也是呼叫引用型變數所屬的類中的成員變數。
簡單記:編譯和執行都參考等號的左邊。編譯執行看左邊。

多型出現後會導致子父類中的成員方法有微弱的變化。看如下程式碼

class Fu {
	int num = 4;
	void show()	{
		System.out.println("Fu show num");
	}
}
class Zi extends Fu {
	int num = 5;
	void show()	{
		System.out.println("Zi show num");
	}
}
class Demo {
	public static void main(String[] args) 	{
		Fu f = new Zi();
		f.show();
	}
}

 多型成員方法
編譯時期:參考引用變數所屬的類,如果沒有類中沒有呼叫的方法,編譯失敗。
執行時期:參考引用變數所指的物件所屬的類,並執行物件所屬類中的成員方法。
簡而言之:編譯看左邊,執行看右邊。

package cn.itcast.demo06;

public class Fu {
	int a = 1;
	public void show(){
		System.out.println("父類的方法");
	}
}

package cn.itcast.demo06;

public class Zi extends Fu{
	int a = 2;
	public void show(){
		System.out.println("子類的方法");
	}
}

package cn.itcast.demo06;
/*
 * 多型中,成員特點
 * 
 * 成員變數:
 * 		編譯的時候,參考父類中有沒有這個變數,如果有,編譯成功,沒有編譯失敗
 * 		執行的時候,執行的是父類中的變數值
 * 編譯執行全看父類
 * 
 * 成員方法:
 * 		編譯的時候,參考父類中有沒有這個方法,如果有,編譯成功,沒有編譯失敗
 * 		執行的時候,執行的是子類的重寫方法
 * 編譯看父類,執行看子類
 */
public class Test {

	public static void main(String[] args) {
		Fu f = new Zi();
		System.out.println(f.a);
		f.show();
		
		//這根本不是多型,就是子類的例項化,呼叫子類的方法和成員變數
		Zi z = new Zi();
		System.out.println(z.a);
		
	}

}

在這裡插入圖片描述
2.4 instanceof關鍵字
我們可以通過instanceof關鍵字來判斷某個物件是否屬於某種資料型別。如學生的物件屬於學生類,學生的物件也屬於人類。
使用格式:

boolean  b  = 物件  instanceof  資料型別;

Person p1 = new Student(); // 前提條件,學生類已經繼承了人類
boolean flag = p1 instanceof Student; //flag結果為true
boolean flag2 = p2 instanceof Teacher; //flag結果為false
package cn.itcast.demo07;

public abstract class Animal {
	
}

package cn.itcast.demo07;

public abstract class Person {
	public abstract void sleep();
}

package cn.itcast.demo07;

public class Student extends Person {

	@Override
	public void sleep() {
		System.out.println("學生在睡覺");
	}

}

package cn.itcast.demo07;
/*
 * 運算子比較運算子,結果真假值
 * 關鍵字 instanceof,比較引用資料型別
 * Cat < Dog
 * Person p = new Student();
 * p = new Teacher()
 * p = new Worker()
 * 關鍵字instanceof比較,一個引用型別的變數,是不是這個型別的物件
 * p變數,是Student型別物件,還是Teacher型別物件
 * 
 * 引用變數instanceof類名
 * p instanceof Student 比較,p是不是Student型別的物件,如果是,instanceof返回true
 * 
 */
public class Test {

	public static void main(String[] args) {
		Person p = new Student();
		//p instanceof Student 比較,p是不是Student型別的物件,如果是,instanceof返回true
		boolean b = p instanceof Student;
		System.out.println(b);
		//Incompatible conditional operand types Person and Animal
		//只對有繼承關係,或者類的實現關係有用
		//b = p instanceof Animal;
		p.sleep();
	}

}

在這裡插入圖片描述
2.5 多型-轉型
多型的轉型分為向上轉型與向下轉型兩種:
 向上轉型:當有子類物件賦值給一個父類引用時,便是向上轉型,多型本身就是向上轉型的過程。
使用格式:

父類型別  變數名 = new 子類型別();
如:Person p = new Student();

 向下轉型:一個已經向上轉型的子類物件可以使用強制型別轉換的格式,將父類引用轉為子類引用,這個過程是向下轉型。如果是直接建立父類物件,是無法向下轉型的!
使用格式:

子類型別 變數名 = (子類型別) 父類型別的變數;
如:Student stu = (Student) p;  //變數p 實際上指向Student物件

2.6 多型的好處與弊端
當父類的引用指向子類物件時,就發生了向上轉型,即把子類型別物件轉成了父類型別。向上轉型的好處是隱藏了子類型別,提高了程式碼的擴充套件性。
但向上轉型也有弊端,只能使用父類共性的內容,而無法使用子類特有功能,功能有限制。看如下程式碼

//描述動物類,並抽取共性eat方法
abstract class Animal {
	abstract void eat();
}
 
// 描述狗類,繼承動物類,重寫eat方法,增加lookHome方法
class Dog extends Animal {
	void eat() {
		System.out.println("啃骨頭");
	}

	void lookHome() {
		System.out.println("看家");
	}
}

// 描述貓類,繼承動物類,重寫eat方法,增加catchMouse方法
class Cat extends Animal {
	void eat() {
		System.out.println("吃魚");
	}

	void catchMouse() {
		System.out.println("抓老鼠");
	}
}

public class Test {
	public static void main(String[] args) {
		Animal a = new Dog(); //多型形式,建立一個狗物件
		a.eat(); // 呼叫物件中的方法,會執行狗類中的eat方法
		// a.lookHome();//使用Dog類特有的方法,需要向下轉型,不能直接使用
		
		// 為了使用狗類的lookHome方法,需要向下轉型
// 向下轉型過程中,可能會發生型別轉換的錯誤,即ClassCastException異常
		// 那麼,在轉之前需要做健壯性判斷 
		if( !a instanceof Dog){ // 判斷當前物件是否是Dog型別
		 		System.out.println("型別不匹配,不能轉換"); 
		 		return; 
		} 
		Dog d = (Dog) a; //向下轉型
		d.lookHome();//呼叫狗類的lookHome方法
	}
}

我們來總結一下:
 什麼時候使用向上轉型:
當不需要面對子類型別時,通過提高擴充套件性,或者使用父類的功能就能完成相應的操作,這時就可以使用向上轉型。

如:Animal a = new Dog();
    a.eat();

 什麼時候使用向下轉型
當要使用子類特有功能時,就需要使用向下轉型。

如:Dog d = (Dog) a; //向下轉型
	    d.lookHome();//呼叫狗類的lookHome方法

 向下轉型的好處:可以使用子類特有功能。
 弊端是:需要面對具體的子類物件;在向下轉型時容易發生ClassCastException型別轉換異常。在轉換之前必須做型別判斷

如:if( !a instanceof Dog){…}
package cn.itcast.demo08;

public abstract class Animal {
	public abstract void eat();
}

package cn.itcast.demo08;

public class Cat extends Animal {
	public void eat(){
		System.out.println("貓吃貓糧");
	}
	public void catchMouse(){
		System.out.println("貓抓老鼠");
	}
}

package cn.itcast.demo08;

public class Dog extends Animal {
	public void eat(){
		System.out.println("狗吃狗糧");
	}
	public void lookHome(){
		System.out.println("狗看家");
	}
}

package cn.itcast.demo08;
/*
 * 測試類:
 * 	1.實現動物和Cat,Dog多型呼叫
 * 	2.做型別的強制轉換,呼叫子類的特有功能
 */
public class Test {

	public static void main(String[] args) {
		//兩個子類,使用兩次的多型呼叫
		Animal a1 = new Cat();
		Animal a2 = new Dog();
		//a1,a2呼叫子類父類共有的方法,執行子類的重寫方法
		a1.eat();
		a2.eat();
		
		//型別向下轉換,強制轉換,呼叫子類的特有
		//防止發生異常:a1屬於Cat物件,轉成Cat類,呼叫自己的特有方法
		//a2屬於Dog物件,轉成Dog類
		if(a1 instanceof Cat){
			Cat c = (Cat)a1;
			c.catchMouse();
		}
		
		if(a2 instanceof Dog){
			Dog c = (Dog)a2;
			c.lookHome();
		}
	}

}

在這裡插入圖片描述
在這裡插入圖片描述
2.7 總結下封裝、繼承、多型的作用:
 封裝:把物件的屬性與方法的實現細節隱藏,僅對外提供一些公共的訪問方式
 繼承:子類會自動擁有父類所有可繼承的屬性和方法。
 多型:配合繼承與方法重寫提高了程式碼的複用性與擴充套件性;如果沒有方法重寫,則多型同樣沒有意義。
第3章 膝上型電腦案例
3.1 案例介紹
定義USB介面(具備開啟功能、關閉功能),筆記本要使用USB裝置,即筆記本在生產時需要預留可以插入USB裝置的USB介面,即就是筆記本具備使用USB裝置的功能,但具體是什麼USB裝置,筆記本並不關心,只要符合USB規格的裝置都可以。滑鼠和鍵盤要想能在電腦上使用,那麼滑鼠和鍵盤也必須遵守USB規範,不然滑鼠和鍵盤的生產出來無法使用
進行描述筆記本類,實現筆記本使用USB滑鼠、USB鍵盤
 USB介面,包含開啟功能、關閉功能
 筆記本類,包含執行功能、關機功能、使用USB裝置功能
 滑鼠類,要符合USB介面
 鍵盤類,要符合USB介面
3.2 案例需求分析
階段一:
使用筆記本,筆記本有執行功能,需要筆記本物件來執行這個功能
階段二:
想使用一個滑鼠,又有一個功能使用滑鼠,並多了一個滑鼠物件。
階段三:
還想使用一個鍵盤 ,又要多一個功能和一個物件
問題:每多一個功能就需要在筆記本物件中定義一個方法,不爽,程式擴充套件性極差。
降低滑鼠、鍵盤等外圍裝置和膝上型電腦的耦合性。

package cn.itcast.demo09;
/*
 * 定義筆記本類
 * 功能:開機,關機,使用USB裝置
 */
public class Computer {
	public void openComputer(){
		System.out.println("電腦開機");
	}
	public void closeComputer(){
		System.out.println("電腦關機");
	}
	//使用USB裝置方法,哪個裝置
	//方法的引數,就是USB裝置
	//				   USB usb = new Mouse()
	public void useUSB(USB usb){
		// 判斷是否有USB裝置
		if (usb != null){
			usb.open();
			usb.close();
		}else{
			System.out.println("沒有USB裝置");
		}
	}
}

package cn.itcast.demo09;
/*
 * 自定義的USB介面類
 * 規範,就是抽象方法
 * 開,關
 */
public interface USB {
	public abstract void open();
	public abstract void close();
}

package cn.itcast.demo09;

public class KeyBoard implements USB{
	@Override
	public void open() {
		System.out.println("鍵盤開啟");
	}

	@Override
	public void close() {
		System.out.println("鍵盤關閉");
	}
}

package cn.itcast.demo09;
/*
 * USB的實現類
 */
public class Mouse implements USB {

	@Override
	public void open() {
		System.out.println("滑鼠開啟");
	}

	@Override
	public void close() {
		System.out.println("滑鼠關閉");
	}

}

package cn.itcast.demo09;

public class Test {

	public static void main(String[] args) {
		//建立筆記本物件,呼叫筆記本的功能
		Computer com = new Computer();
		com.openComputer();
		//呼叫筆記本使用USB裝置的方法
		//引數,是USB介面型別,介面不能建立物件
		//呼叫方法,傳遞USB介面的實現類的物件
		//Mouse m = new Mouse();
		com.useUSB(new Mouse());
		com.useUSB(new KeyBoard());
		com.closeComputer();
		
	}

}

在這裡插入圖片描述
第4章 總結
4.1 知識點總結
 介面:理解為是一個特殊的抽象類,但它不是類,是一個介面
 介面的特點:
1,定義一個介面用interface關鍵字
interface Inter{}
2,一個類實現一個介面,實現implements關鍵字
class Demo implements Inter{}
3, 介面不能直接建立物件
通過多型的方式,由子類來建立物件,介面多型
 介面中的成員特點:
成員變數:
只能是final 修飾的常量
預設修飾符: public static final
構造方法:

成員方法:
只能是抽象方法
預設修飾符: public abstract (介面中許可權只能是public)
 類與類,類與介面,介面與介面之間的關係
類與類之間:繼承關係,單繼承,可以是多層繼承
類與介面之間: 實現關係,單實現,也可以多實現
介面與介面之間:繼承關係,單繼承,也可以是多繼承
Java中的類可以繼承一個父類的同時,實現多個介面

 多型:理解為同一種物質的多種形態
 多型使用的前提:
1,有繼承或者實現關係
2,要方法重寫
3,父類引用指向子類物件
 多型的成員訪問特點:
方法的執行(執行看子類)看右邊,其他都看左邊(編譯看父類)
 多型的好處:
提高了程式的擴充套件性
 多型的弊端:
不能訪問子類的特有功能
 多型的分類
 類的多型

abstract class Fu {
                  public abstract void method();
}
class Zi extends Fu {
public void method(){
		             System.out.println(“重寫父類抽象方法”);
}
}
//類的多型使用
Fu fu= new Zi();

 介面的多型

interface Fu {
	public abstract void method();
}
class Zi implements Fu {
	public void method(){
        System.out.println(“重寫介面抽象方法”);
}
}
//介面的多型使用
Fu fu = new Zi();

 instanceof 關鍵字
格式: 物件名 instanceof 類名
返回值: true, false
作用: 判斷指定的物件 是否為 給定類建立的物件