第十一天 面向物件-介面&多型【悟空教程】
第11天 面向物件
第1章 介面
1.1 介面概念
1.1.1 介面概念
介面是功能的集合,同樣可看做是一種資料型別,是比抽象類更為抽象的”類”。
介面只描述所應該具備的方法,並沒有具體實現,具體的實現由介面的實現類(相當於介面的子類)來完成。這樣將功能的定義與實現分離,優化了程式設計。
請記住:一切事物均有功能即一切事物均有介面。
繼承是方便類的定義,可以定義一個共性的父類 然後設定子類在繼承,提高程式碼複用性
介面是方便了方法的使用 比如企鵝是鳥 但他不會飛 如果我們設定鳥類都會飛的方法就不合適,所以這時我們定義一個飛的介面那麼到時那個鳥呼叫這個介面那個鳥就會飛了,介面是方便了方法的實現,提高程式碼的耦合性,使程式碼擴充套件性提高。
1.1.2 介面的程式碼體現
在程式碼體現中,介面的更為抽象表現為其內的所有方法均為抽象方法,同時不定義普通的成員變數(可以定義靜態常量,在後邊介紹)。
如同抽象類,介面在使用時同樣不能建立物件。
類與介面的關係為實現關係,即類實現介面。實現的動作類似繼承,只是關鍵字不同,實現使用implements。
其他類(實現類)實現介面後,就相當於宣告:”我應該具備這個介面中的功能”。實現類仍然需要重寫方法以實現具體的功能。
1.2 介面定義及使用格式
1.2.1 介面定義
a) 定義關鍵字
與定義類的class不同,介面定義時需要使用interface關鍵字。
定義介面所在的仍為.java檔案,雖然宣告時使用的為interface關鍵字的編譯後仍然會產生.class檔案。這點可以讓我們將介面看做是一種只包含了功能宣告的特殊類。
b) 定義格式
使用interface代替了原來的class,其他步驟與定義類相同:
-
方法均為公共訪問的抽象方法
-
無法定義普通的成員變數
public interface 介面名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
如:
public interface Careable {
public abstract void carCare();
}
}
1.2.2 介面使用
a) 類實現介面
我們使用實現來表示一個類與一個介面之間的關係,這是最常用的使用方法。
實現的關鍵字為implements。
格式:
Class 類 implements 介面 {
重寫介面中方法
}
在實現後,該類就會將介面中的抽象方法繼承過來,此時該類需要重寫該抽象方法,完成具體的邏輯。
則:
-
介面中定義功能,一切類需要具有該功能時均可以實現該介面,只聲明瞭應該具備該方法,是功能的宣告。
-
具體實現類中重寫方法,實現功能,是方法的具體實現。
於是,通過以上兩個動作將功能的宣告與實現便分開了。(此時請重新思考:類是現實事物的描述,介面是功能的集合。)
/*
* 哺乳動物
*
* 姓名
* 年齡
*
* 吃 睡
*/
public abstract class BRDW {
private String name;
private int age;
public abstract void eat();
public abstract void sleep();
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 class BianFu extends BRDW implements Fly{
@Override
public void eat() {
System.out.println("蝙蝠吃蛾子");
}
@Override
public void sleep() {
System.out.println("蝙蝠倒掛著睡");
}
@Override
public void open() {
System.out.println("開啟小翅膀");
}
@Override
public void fly(double height) {
System.out.println("蝙蝠能飛"+height+"米高");
}
@Override
public void close() {
System.out.println("關閉小翅膀");
}
}
/*
* 飛的介面
*
* 展開翅膀
*
* 飛
*
* 著陸(關閉翅膀)
*
* 方法均為公共訪問的抽象方法
*/
public interface Fly {
//展開翅膀
public abstract void open();
//飛
public abstract void fly(double height);
//關閉翅膀
public abstract void close();
}
/*
* 哺乳動物
* 老虎 蝙蝠
*/
public class Test {
public static void main(String[] args) {
BianFu bf = new BianFu();
bf.eat();
bf.sleep();
bf.open();
bf.fly(250.0);
bf.close();
}
}
//老虎沒有實現介面所以老虎就沒有飛的功能
/*
* 哺乳動物
* 老虎 蝙蝠
*/
public class Test {
public static void main(String[] args) {
BianFu bf = new BianFu();
bf.eat();
bf.sleep();
bf.open();
bf.fly(250.0);
bf.close();
}
}
b) 介面繼承介面
如同類繼承類後便擁有了父類的成員,可以使用父類的非私有成員。A介面繼承B介面後,A介面便擁有了A、B兩個介面中所有的抽象方法。並集關係。
c) 定義介面變數使用多型
介面經常參與多型。在後邊多型時,我們詳細講解。
這裡我們需要清楚,介面也是一種特殊的資料型別,就可以定義變數、作為引數宣告、作為返回值宣告、作為成員變數宣告。
package cn.javahelp.test;
/*
* Animal的類
* 屬性
* name
* age
* 行為
* 吃
* 睡
*/
public abstract class Animal {
//成員變數
private String name;
private int age;
//吃
public void eat(){
System.out.println("動物吃");
}
//睡
public void sleep(){
System.out.println("睡");
}
//-----------get/set-------------------
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;
}
}
package cn.javahelp.test;
/*
* 定義看門介面
*/
public interface LookDoor {
public abstract void lookDoor();
}
package cn.javahelp.test;
/*
* 自定義型別 家
*
* 地址
*
* 行為
* 在家吃飯
*/
public class Home {
private String address;
//動物在家吃飯
//在所有使用父類型別的地方均可以傳入其子類物件。
public void eatAtHome(Animal a){
//呼叫Animal的eat方法
a.eat();
}
//看家方法
public void lookHome(LookDoor lk){
//呼叫狗看門的方法
lk.lookDoor();
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
package cn.javahelp.test;
/*
*定義一個狗類
* 屬性
* name
* age
* kind
* 行為
* 吃
* 睡
* 看門
*/
public class Dog extends Animal implements LookDoor{
private String kind;
@Override
public void eat(){
System.out.println("狗吃肉");
}
//狗特有功能 看門
@Override
public void lookDoor(){
System.out.println("狗看門");
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
}
package cn.javahelp.test;
public class Pig extends Animal implements LookDoor{
@Override
public void lookDoor() {
System.out.println("豬看門");
}
@Override
public void eat() {
System.out.println("豬吃");
}
}
package cn.javahelp.test;
/**
* 測試家類
*
* 任何使用父類或父介面的地方都可以傳入其子類(實現類物件)物件
*/
public class Test {
public static void main(String[] args) {
//建立Home物件
Home home = new Home();
Dog d = new Dog();
//lookHome需要的是一個看門的介面 我傳入的實際引數是一個實現類的物件
home.lookHome(d);
Pig p = new Pig();
home.lookHome(p);
//--------------------------------
System.out.println("-----------------------");
Cat cat = new Cat();
Animal a = new Cat();
home.eatAtHome(cat);
}
public static Animal get(){
Animal a = new Dog();
return a;
}
}
1.3 介面注意事項
-
Java支援一個類同時實現多個介面。
一個類可以有多個介面書寫加上逗號即可implements List<E>,RandomAccess,Cloneable
-
Java支援一個介面同時繼承多個介面。這裡取並集。C繼承A和B同時擁有AB的方法。
-
類可以在繼承一個類的同時,實現多個介面。
子類繼承父類與介面中的方法,當父類和介面的方法相同時,子類只需要實現一次即可。
-
介面與父類的功能可以重複,均代表要具備某種功能,並不衝突。
-
介面中的成員是有固定修飾符abstract的,如果沒有寫,也會自動加入:(介面中都是常量沒有變數)
新建一個介面
public abstract interface Fu{
public void fly();
}
我們把abstract去掉在fly方法中加入方法體看下報錯說明,證明介面自動加入了修飾符abstract,因為抽象類是沒有方法體的。寫上方法體eclipse自動報錯修正。
“變數”修飾符為:public static final(static與final面向物件第5天講解)
方法修飾符為:public abstract(所以依據方法重寫的訪問許可權注意事項,重寫介面方法時,必須使用public)
public abstract interface Fu{
public void fly();
}
public class Zi implements Fu{
@Override
Public void fly(){
}
}
這裡我們把父類的public去掉 也把子類的public去掉那麼會看到子類會報錯,eclipse提示要 新增public。這裡建議大家永遠加上public abstract。
-
當一個類實現了介面時,必須實現其所有的方法,否則這個類會保留一些抽象方法,此時,該類包含了抽象方法,便必須定義為一個抽象類。
比如:介面中有三個方法,你實現了兩個方法,那麼還包含了一個抽象方法,那這個類也必須是一個抽象類。
-
接口裡面可以沒有任何方法。
雖然介面是功能的集合,沒有方法沒有意義,此時這個介面的作用就是一個標記,像宋江被臉上打上標記一樣,就是讓你知道。
1.4 介面的思想
前面學習了介面的程式碼體現,現在來學習介面的思想,接下里從生活中的例子進行說明。
舉例:我們都知道電腦上留有很多個插口,而這些插口可以插入相應的裝置,這些裝置為什麼能插在上面呢?主要原因是這些裝置在生產的時候符合了這個插口的使用規則,否則將無法插入介面中,更無法使用。發現這個插口的出現讓我們使用更多的裝置。
總結:介面在開發中的它好處
1、介面的出現擴充套件了功能。
2、介面其實就是暴漏出來的規則。
3、介面的出現降低了耦合性,即裝置與裝置之間實現瞭解耦。
介面的出現方便後期使用和維護,一方是在使用介面(如電腦),一方在實現介面(插在插口上的裝置)。例如:筆記本使用這個規則(介面),電腦外圍裝置實現這個規則(介面)。
1.5 介面和抽象類的區別
明白了介面思想和介面的用法後,介面和抽象類的區別是什麼呢?介面在生活體現也基本掌握,那在程式中介面是如何體現的呢?
通過例項進行分析和程式碼演示抽象類和介面的用法。
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 緝毒() {
}
}
1.5.1 介面和抽象類的相同點
-
都位於繼承的頂端,用於被其他類實現或繼承;
-
都不能直接例項化物件;
-
都包含抽象方法,其子類都必須覆寫這些抽象方法;
1.5.2 介面和抽象類的區別:
-
抽象類為部分方法提供實現,避免子類重複實現這些方法,提高程式碼重用性;介面只能包含抽象方法;
-
一個類只能繼承一個直接父類(可能是抽象類),卻可以實現多個介面;(介面彌補了Java的單繼承)
1.5.3 介面和抽象類的選用:
-
優先選用介面,儘量少用抽象類;
需要定義子類的行為,又要為子類提供共性功能時才選用抽象類;
1.5.4 介面和抽象類的使用區別總結
-
類繼承類extends,只能單繼承
介面繼承介面extends可以多繼承
類實現介面implements可以多實現
介面不可以繼承類!
-
抽象類中可以有非抽象方法
介面中全部為抽象方法
-
抽象類具有成員變數
介面沒有普通的成員變數
-
抽象類中的成員無固定修飾符
介面中的成員有固定修飾符
第2章 多型
2.1 多型概述
多型是繼封裝、繼承之後面向物件的第三大特性。
現實事物經常會體現出多種形態,如學生,學生是人的一種,則一個具體的同學張三既是學生也是人,即出現兩種形態。
Java作為面向物件的語言,同樣可以描述一個事物的多種形態。如Student類繼承了Person類,一個Student的物件便既是Student,又是Person。
2.2 多型概念
Java中多型的程式碼體現在一個子類物件(實現類物件)既可以給這個子類(實現類物件)引用變數賦值,又可以給這個子類(實現類物件)的父類(介面)變數賦值。
如Student類可以為Person類的子類。那麼一個Student物件既可以賦值給一個Student型別的引用,也可以賦值給一個Person型別的引用。
最終多型體現為父類引用變數可以指向子類物件。
多型的前提是必須有子父類關係或者類實現介面關係,否則無法完成多型。
在使用多型後的父類引用變數呼叫方法時,會呼叫子類重寫後的方法。
Animal a = new Cat(); 貓是一個動物
多型優點:
配合繼承與方法重寫提高了程式碼的複用性與擴充套件性,如果沒有方法重寫,則多型同樣沒有意義。
2.3 多型的定義與使用格式
父類引用指向子類物件就是多型的定義格式。同一個父類的方法會被不同的子類重寫為各自的具體實現。在呼叫方法時,呼叫的為各個子類重寫後的方法。呼叫父類的功能執行的是子類重寫後的功能
父類型別 變數名 = new 子類型別();
變數名.方法名();
此時,雖然該變數指向的是子類物件,但表現為一個父類的形態,可以呼叫一切父類的方法,子類特有的方法將不能呼叫。
2.4 多型的使用場景
我們一般在以下場景當中使用多型:
-
成員變數賦值、區域性變數賦值
-
方法傳參
-
返回值返回值
2.5 多型的存在意義
當變數名指向不同的子類物件時,由於每個子類重寫父類方法的內容不同,所以會呼叫不同的方法。
如:
在Boss類中,有叫員工去工作的方法,當該方法的引數定義為介面時,可以傳入任意的子類物件。相比定義多個子類引數,定義多個方法,這樣大大提高了程式碼複用性與擴充套件性。
class Boss{
public void goToWork(Empolyee e){
e.work();
}
}
所以多型的存在意義(優點)為:
配合繼承與方法重寫提高了程式碼的複用性與擴充套件性,如果沒有方法重寫,則多型同樣沒有意義。
2.6 instanceof關鍵字
我們可以通過instanceof關鍵字來判斷某個物件是否屬於某種資料型別。如學生的物件屬於學生類,學生的物件也屬於人類。
使用格式:
boolean b = 物件 instanceof 資料型別
2.7 向上轉型與向下轉型
多型本身是子類型別向父類型別向上轉型的過程。
多型的轉型分為向上轉型與向下轉型兩種:
-
向上轉型:當有子類物件賦值給一個父類引用時,便是向上轉型,多型本身就是向上轉型的過程。
使用格式:
父類型別 變數名 = new 子類型別();
如:Person p = new Student();
-
向下轉型:一個已經向上轉型的子類物件可以使用強制型別轉換的格式,將父類引用轉為子類引用,這個過程是向下轉型。如果是直接建立父類物件,是無法向下轉型的!
使用格式:
子類型別 變數名 = (子類型別) 父類型別的變數;
如:Student stu = (Student) p; //變數p 實際上指向Student物件
2.8 多型細節規則
-
編譯時,檢查父類引用變數的資料型別是否包含對應的成員方法與成員變數。
-
執行時,成員方法呼叫子類重寫方法,沒有用private修飾的成員變數訪問時,訪問的為父類型別的。
-
或簡單記憶:只有在呼叫方法時,呼叫的時子類重寫方法,其他一切表現均為父類型別。
public class Fu {
String name = "父類名字" ;
public void method(){
System.out.println("父類方法");
}
}
public class Zi extends Fu{
String name = "子類名字";
int age ;
@Override
public void method(){
System.out.println("子類方法");
}
public void method2(){
System.out.println("子類特有方法");
}
}
/*
* 向上轉型
* 多型 父類引用指向子類物件 這本身就是向上轉型
* 當呼叫方法時,呼叫的是父類的方法 但是在執行時執行的是子類重寫後的方法
* 不能呼叫子類特有的方法
* 例如:
* 向上轉型:有人請你父親去講課,父親不在,你穿上你父親的衣服去講課,你講的內容肯定是你自己的;
* 向下轉型:你自己有打遊戲的方法但是你要脫下衣服變回兒子才能去打遊戲。
*
* 列印成員變數時,列印的是父類的
*
* 向下轉型
* 當本身是子類物件,向上轉型為父類型別後,可以通過強制型別轉換,轉換回子類物件
*
*多型時
* 編譯時
* 成員方法 看等號左邊
* 成員變數 看等號左邊
* 執行時
* 成員方法 看等號右邊
* 成員變數 看等號左邊
*
*/
public class Test {
public static void main(String[] args) {
Fu fu = new Fu();
fu.method();
Zi zi = new Zi();
zi.method();
zi.method2();
System.out.println("----------------------");
//多型本身就是向上轉型
Fu fz = new Zi();
//向上轉型後,一切表現形式都是父類的表現形式,不能呼叫子類特有的功能
fz.method();
//型別強轉回顧
//double b = 12.0;
//int a = (int)b;
//向下轉型 使用強制型別轉換進行轉換
Zi zf = (Zi)fz;
//向下轉向那個後可以呼叫子類特有方法
zf.method();
zf.method2();
System.out.println("================");
System.out.println(fz.name);
System.out.println("=============");
//本身就是父類物件不可以轉換成子類
//Zi z = (Zi)fu;
}
}
第3章 綜合案例---家養寵物案例
3.1 案例介紹與演示
題目要求1(多型):
定義家類
方法:飼養動物
動物類:
屬性:年齡、姓名
方法:吃飯、睡覺
貓類、狗類、豬類均為動物類的一種。
建立家類物件,呼叫家的飼養動物方法。
題目要求2(介面與多型):
定義看門的功能介面:
方法:看門
家類中新增新的功能:安排寵物看家方法
假設:豬和狗具備看家的功能
建立家類物件,呼叫安排寵物看家的方法
3.2 案例分析
題目要求1(多型):
家類飼養動物方法定義時為父類,即動物類,則在呼叫飼養動物時,可以傳入任意的子類物件,貓、狗、豬均可。
/*
* 動物類
* 屬性:年齡、姓
* 方法:吃飯、睡覺
*/
public abstract class Animal {
private String name;
private int age;
public abstract void eat();
public abstract void sleep();
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 class Cat extends Animal{
@Override
public void eat() {
System.out.println("貓吃魚");
}
@Override
public void sleep() {
System.out.println("貓躺著睡");
}
public void catchMouse(){
System.out.println("貓抓老鼠");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("趴著睡");
}
}
public class Pig extends Animal implements LookDoor{
@Override
public void eat() {
System.out.println("豬什麼都吃");
}
@Override
public void sleep() {
System.out.println("豬吃完了就睡");
}
}
/*
* 飼養動物方法
*/
public class Home {
//飼養動物的方法
public void feedAnimal(Animal a){
a.eat();
}
}
/*
* 測試 家類 飼養動物方法
*/
public class Test {
public static void main(String[] args) {
Home home = new Home();
Animal a = new Dog();
Cat c = new Cat();
home.feedAnimal(a);
}
}
題目要求2(介面與多型):
家類看家的方法定義時無法為動物類,因為並不是所有的類均有看門的方法,這裡設計為狗與豬類具有看門的方法,則二者可以實現看門介面,獲取看門方法,重寫看門方法。在定義看門的方法時,定義接收看門介面的型別。則在實際呼叫方法時,只要是實現了該介面的類的物件均可以傳入。
/*
* 動物類
* 屬性:年齡、姓
* 方法:吃飯、睡覺
*/
public abstract class Animal {
private String name;
private int age;
public abstract void eat();
public abstract void sleep();
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 interface LookDoor {
public abstract void lookDoor();
}
public class Dog extends Animal implements LookDoor{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("趴著睡");
}
@Override
public void lookDoor() {
System.out.println("狗汪汪的看門,逮誰咬誰!");
}
}
public class Pig extends Animal implements LookDoor{
@Override
public void eat() {
System.out.println("豬什麼都吃");
}
@Override
public void sleep() {
System.out.println("豬吃完了就睡");
}
@Override
public void lookDoor() {
System.out.println("豬哼哼的看門,專拱白菜");
}
}
/*
* 飼養動物方法
*/
public class Home {
//飼養動物的方法
public void feedAnimal(Animal a){
a.eat();
}
//安排寵物看家的方法
public void lookHome(LookDoor lk){
lk.lookDoor();
}
}
/*
* 測試 家類 飼養動物方法
*/
public class Test {
public static void main(String[] args) {
Home home = new Home();
Animal a = new Dog();
Cat c = new Cat();
home.feedAnimal(a);
//多型
LookDoor lk = new Dog();
LookDoor lk2 = new Pig();
home.lookHome(lk2);
}
}
第4章 膝上型電腦案例
4.1 案例介紹
定義USB介面(具備開啟功能、關閉功能),筆記本要使用USB裝置,即筆記本在生產時需要預留可以插入USB裝置的USB介面,即就是筆記本具備使用USB裝置的功能,但具體是什麼USB裝置,筆記本並不關心,只要符合USB規格的裝置都可以。滑鼠和鍵盤要想能在電腦上使用,那麼滑鼠和鍵盤也必須遵守USB規範,不然滑鼠和鍵盤的生產出來無法使用
進行描述筆記本類,實現筆記本使用USB滑鼠、USB鍵盤
-
USB介面,包含開啟功能、關閉功能
-
筆記本類,包含執行功能、關機功能、使用USB裝置功能
-
滑鼠類,要符合USB介面
-
鍵盤類,要符合USB介面
4.2 案例需求分析
階段一:
使用筆記本,筆記本有執行功能,需要筆記本物件來執行這個功能
階段二:
想使用一個滑鼠,又有一個功能使用滑鼠,並多了一個滑鼠物件。
階段三:
還想使用一個鍵盤 ,又要多一個功能和一個物件
問題:每多一個功能就需要在筆記本物件中定義一個方法,不爽,程式擴充套件性極差。
降低滑鼠、鍵盤等外圍裝置和膝上型電腦的耦合性。
4.3 實現程式碼步驟
-
定義滑鼠、鍵盤,筆記本三者之間應該遵守的規則
interface USB {
void open();// 開啟功能
void close();// 關閉功能
}
l 滑鼠實現USB規則
class Mouse implements USB {
public void open() {
System.out.println("滑鼠開啟");
}
public void close() {
System.out.println("滑鼠關閉");
}
}
-
鍵盤實現USB規則
class KeyBoard implements USB {
public void open() {
System.out.println("鍵盤開啟");
}
public void close() {
System.out.println("鍵盤關閉");
}
}
-
定義筆記本
class NoteBook {
// 筆記本開啟執行功能
public void run() {
System.out.println("筆記本執行");
}
// 筆記本使用usb裝置,這時當筆記本物件呼叫這個功能時,必須給其傳遞一個符合USB規則的USB裝置
public void useUSB(USB usb) {
// 判斷是否有USB裝置
if (usb != null) {
usb.open();
usb.close();
}
}
public void shutDown() {
System.out.println("筆記本關閉");
}
}
public class Test {
public static void main(String[] args) {
// 建立筆記本實體物件
NoteBook nb = new NoteBook();
// 筆記本開啟
nb.run();
// 建立滑鼠實體物件
Mouse m = new Mouse();
// 筆記本使用滑鼠
nb.useUSB(m);
// 建立鍵盤實體物件
KeyBoard kb = new KeyBoard();
// 筆記本使用鍵盤
nb.useUSB(kb);
// 筆記本關閉
nb.shutDown();
}
}
第5章 本日自習作業:
5.1 知識點相關題
5.1.1 什麼是介面?如何定義介面?
5.1.2 介面與抽象類有哪些不同?
5.1.3 多型是什麼?或者多型的程式碼體現是什麼?
5.1.4 如何使用多型(至少說出2種多型的具體使用方式程式碼),一定要使用多型麼?多型有什麼好處? 試舉一例,說明多型的好處。
5.1.5 產生多型後,使用變數時,是父類的表現還是子類的表現?驗證語法錯誤看子類還是父類,呼叫方法時,呼叫子類方法還是父類方法?
5.1.6 instanceof關鍵字有什麼作用
5.1.7 嘗試使用介面/抽象類作為成員變數型別,並賦值(瞭解)
如:家類有”家庭寵物”的成員變數,家庭寵物為Animal型別,而Animal可以繼續有子類。則在給家類的家庭寵物變數賦值時,可以給予子類物件賦值。
5.1.8 以下對介面描述錯誤的有()
A) 介面沒有提供構造方法
B) 介面中的方法預設使用public、abstract修飾
C) 介面中的屬性預設使用public、static、final修飾
D) 介面不允許多繼承
答案:D
5.1.9 有關介面的描述不正確的是
A介面是一種引用型別
B介面支援多繼承
C介面中的方法都沒有方法體
D一個介面可以繼承其他介面的變數
答案:D
5.1.10 以下哪個介面的定義是正確的?
A.interface B{void print() { } }
B.abstract interface B { void print() }
C.abstract interface B extends A1,A2 { abstract void print(){ };
D.interface B { void print();}
答案:D
5.1.11 Java中能實現多重繼承功能的方式是?
A.介面
B.同步
C.抽象類
D.父類
答案:A
5.1.12 下列敘述正確的是?
A.Java中允許多重繼承
B.Java一個類只能實現一個介面
C.Java中只能單重繼承
D.Java中一個類可以繼承多個抽象類
答案:C
5.1.13 以下程式執行的結果是:
public class EE { public static void main(String[] args) { A a = new B(); a.show(); B b = new C(); b.show(); } } class A { public void show() { show2(); } public void show2() { System.out.println("我"); } } class B extends A { public void show2() { System.out.println("愛"); } } class C extends B { public void show() { super.show(); } public void show2() { System.out.println("你"); } } |
答案: 愛 你
5.1.14 有籃球運動員和乒乓球運動員 有籃球教練和乒乓球教練 為了出國比賽 乒乓球相關的人需要學習英語
package cn.javahelp7.test;
/*
* 定義Person
* name age
* 睡吃
*/
public abstract class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
//吃
public abstract void eat();
//睡
public abstract void sleep();
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;
}
}
package cn.javahelp7.test;
/*
*運動員類
*/
public abstract class Player extends Person{
//運動員特有方法 運動
public abstract void play();
public Player() {
super();
}
public Player(String name, int age) {
super(name, age);
}
}
package cn.javahelp7.test;
/*
* 教練類
*/
public abstract class Teacher extends Person{
//教練特有方法 教
public abstract void teacher();
public Teacher() {
super();
}
public Teacher(String name, int age) {
super(name, age);
}
}
package cn.javahelp7.test;
/*
* 兵乓球運動員
*/
public class PPQPlayer extends Player implements IStudyEnglish{
public PPQPlayer() {
super();
}
public PPQPlayer(String name, int age) {
super(name, age);
}
@Override
public void play() {
System.out.println("乒乓球運動員玩乒乓球");
}
@Override
public void eat() {
System.out.println("乒乓球運動員吃乒乓球運動員套餐");
}
@Override
public void sleep() {
System.out.println("乒乓球運動員睡乒乓球運動員公寓");
}
@Override
public void studyEnglish() {
System.out.println("乒乓球運動員學習乒乓球英語");
}
}
package cn.javahelp7.test;
/*
* 乒乓球教練類
*/
public class PPQTeacher extends Teacher implements IStudyEnglish{
public PPQTeacher() {
super();
}
public PPQTeacher(String name, int age) {
super(name, age);
}
@Override
public void teacher() {
System.out.println("乒乓球教練教乒乓球運動員");
}
@Override
public void eat() {
System.out.println("乒乓球教練吃乒乓球教練套餐");
}
@Override
public void sleep() {
System.out.println("乒乓球教練睡乒乓球教練公寓");
}
@Override
public void studyEnglish() {
System.out.println("乒乓球教練學習乒乓球英語");
}
}
package cn.javahelp7.test;
public class LQPlayer extends Player {
public LQPlayer() {
super();
}
public LQPlayer(String name, int age) {
super(name, age);
}
@Override
public void play() {
System.out.println("籃球運動員玩籃球");
}
@Override
public void eat() {
System.out.println("籃球運動員吃籃球運動員套餐");
}
@Override
public void sleep() {
System.out.println("籃球運動員睡籃球運動員公寓");
}
}
package cn.javahelp7.test;
/*
* 籃球教練類
*/
public class LQTeacher extends Teacher{
public LQTeacher() {
super();
}
public LQTeacher(String name, int age) {
super(name, age);
}
@Override
public void teacher() {
System.out.println("籃球教練教籃球運動員");
}
@Override
public void eat() {
System.out.println("籃球教練吃籃球教練套餐");
}
@Override
public void sleep() {
System.out.println("籃球教練睡籃球教練公寓");
}
}
package cn.javahelp7.test;
/*
* 學英語介面
*/
public interface IStudyEnglish {
public abstract void studyEnglish();
}
package cn.javahelp7.test;
public class Test {
public static void main(String[] args) {
//乒乓球運動員物件
PPQPlayer ppqp = new PPQPlayer("劉備",40);
ppqp.eat();
ppqp.sleep();
ppqp.play();
ppqp.studyEnglish();
System.out.println("------------------------");
PPQTeacher ppqt = new PPQTeacher("諸葛亮" ,20);
ppqt.eat();
ppqt.sleep();
ppqt.teacher();
ppqt.studyEnglish();
System.out.println("------------------------");
LQPlayer lqp = new LQPlayer("趙雲",18);
lqp.eat();
lqp.sleep();
lqp.play();
System.out.println(lqp.getName());
System.out.println("------------------------");
LQTeacher lqt = new LQTeacher("呂布",30);
lqt.eat();
lqt.sleep();
lqt.teacher();
lqt.getName();
System.out.println(lqt.getName());
System.out.println(lqt.getAge());
System.out.println(lqt.getClass());
}
}
5.2 程式碼題:
5.2.1 多型成員的特點習題
要求:
1.定義明星類,有姓名和年齡的屬性,且屬性不寫private修飾符,提供無返回值的無引數的自我介紹的方法,方法內容為:”我是明星xxx,我今年xxx歲了;”
2.定義明星的子類,重寫父類的自我介紹的方法,內容為:”我是明星子類,我的名字是xxx,我今年xxx歲了;”,提供一個無引數的無返回值的跳舞的方法,內容為:”我是明星的子類,我跳拉丁舞......”
3.定義測試類,使用多型的形式建立明星的子類的物件,使用該物件分別給姓名和年齡屬性賦值,再呼叫自我介紹的方法,然後通過型別轉換,呼叫子類跳舞的方法;
答案:
/* * 明星類: * 屬性: * 姓名 * 年齡 * 方法: * 自我介紹 */ public class MingXing { //屬性 String name; int age; //自我介紹的方法 public void ziWoJieShao(){ System.out.println("我是明星"+name+",我今年"+age+"歲了;"); } } /* * 明星子類: * 方法: * 自我介紹 * 跳舞 */ public class MingXingZi extends MingXing { //重寫父類的自我介紹的方法 public void ziWoJieShao(){ System.out.println("我是明星子類,我的名字是"+super.name+",我今年"+super.age+"歲了;"); } //跳舞的方法 public void tiaoWu(){ System.out.println("我是明星的子類,我跳拉丁舞......"); } } /* * 測試類 */ public class Test { public static void main(String[] args) { //1、使用多型的形式建立明星的子類的物件 MingXing mx = new MingXingZi(); //2、賦值 mx.name = "德華"; mx.age = 40; //3、呼叫自我介紹的方法 mx.ziWoJieShao(); //4、向下轉型 MingXingZi mxz = (MingXingZi)mx; //5、呼叫跳舞的方法 mxz.tiaoWu(); } } |
5.2.2 引數多型的使用習題
要求:
1.定義動物類,動物類有抽象的無返回值的無引數的“嚎叫”方法;
2.定義貓類,繼承動物類,貓叫的聲音為:“小貓喵喵叫...”,提供無返回值的無引數的抓老鼠的方法,內容為:”小貓抓老鼠...”;
3.定義狗類,繼承動物類,狗叫的聲音為:“小狗汪汪叫...”;
4.定義人類,提供無返回值的帶1個動物型別引數的逗動物玩的方法,在方法內部讓動物嚎叫,且如果該動物是小貓,就讓小貓抓老鼠;
5.定義測試類,分別建立貓的物件,狗的物件,人的物件,用人的物件呼叫逗動物玩的方法,分別測試小貓物件和小狗物件;
答案:
/* * 抽象的動物類: * 方法: * 抽象的嚎叫方法 */ public abstract class DongWu { public abstract void haoJiao(); } /* * 貓類繼承動物類: * 方法: * 嚎叫 * 抓老鼠 */ public class Mao extends DongWu{ //嚎叫的方法 public void haoJiao() { System.out.println("小貓喵喵叫..."); } //抓老鼠的方法; public void zhuaLaoShu() { System.out.println("小貓抓老鼠..."); } } /* * 狗類繼承動物類 */ public class Gou extends DongWu{ //嚎叫的方法 public void haoJiao() { System.out.println("小狗汪汪叫..."); } } /* * 人類: * 方法: * 逗動物玩 */ public class Ren { //逗動物玩 public void douDongWuWan(DongWu d){ //1、讓動物嚎叫 d.haoJiao(); //2、判斷該動物是不是小貓 if(d instanceof Mao){ //3、是貓就強轉成貓型別,呼叫抓老鼠的方法 Mao m = (Mao)d; m.zhuaLaoShu(); } } } /* * 測試類 */ public class Test { public static void main(String[] args) { //1、分別建立貓的物件,狗的物件,人的物件 Mao m = new Mao(); Gou g = new Gou(); Ren r = new Ren(); //2、用人的物件呼叫逗動物玩的方法,分別測試小貓物件和小狗物件 r.douDongWuWan(g); r.douDongWuWan(m); } } |
5.2.3 介面多型的使用習題
要求:
1.定義主持人介面,提供一個無引數無返回值的主持的方法;
2.定義學生類,提供一個無引數的無返回值的抽象的吃方法;
3.定義男同學類,繼承學生類,吃的方法內容為:”我是男同學,我嗑瓜子,喝啤酒...”;
4.定義女同學類,繼承學生類,同時實現主持人介面,主持方法的內容為:”女士們,先生們,大家好,我是主持人......”,吃的方法內容為:”我是女同學,我嗑瓜子,吃水果...”;
5.定義班級類,提供一個無返回值的,帶兩個引數的開晚會的方法,其中第1個引數為主持人介面型別,第二個引數為學生型別,方法內容中要求先呼叫主持人的主持方法,再列印一句話”晚會正式開始.....”,然後呼叫學生的吃的方法;
6.定義測試類,使用多型的形式分別建立學生型別的物件,主持人型別的物件,班級型別的物件(這個物件非多型),使用班級物件呼叫開晚會的方法;
答案:
/* * 主持人介面: * 方法: * 主持 */ public interface ZhuChiRen { public abstract void zhuChi(); } /* * 學生類: * 方法: */ public abstract class XueSheng { public abstract void chi(); } /* * 男同學類,繼承學生類 */ public class NanTongXue extends XueSheng{ public void chi(){ System.out.println("我是男同學,我嗑瓜子,喝啤酒..."); } } /* * 女同學類,繼承學生類,同時實現主持人介面 */ public class NvTongXue extends XueSheng implements ZhuChiRen{ //重寫學生類中的抽象的吃的方法 public void chi(){ System.out.println("我是女同學,我嗑瓜子,吃水果..."); } //實現主持人介面的主持的方法 public void zhuChi() { System.out.println("女士們,先生們,大家好,我是主持人......"); } } /* * 班級類 * 方法: * 開班會 */ public class BanJi { //無返回值的,帶兩個引數的開晚會的方法,其中第1個引數為主持人介面型別,第二個引數為學生型別 public void kaiBanHui(ZhuChiRen z,XueSheng x){ //1、先呼叫主持人的主持方法 z.zhuChi(); //2、列印一句話”晚會正式開始.....” System.out.println("晚會正式開始....."); //3、然後呼叫學生的吃的方法 x.chi(); } } /* * 測試類 */ public class Test { public static void main(String[] args) { //1、使用多型的形式分別建立學生型別的物件,主持人型別的物件, XueSheng x = new NanTongXue(); ZhuChiRen z = new NvTongXue(); //2、建立班級型別的物件(這個物件非多型), BanJi b = new BanJi(); //3、使用班級物件呼叫開晚會的方法 b.kaiBanHui(z, x); } } |