第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); } } |