1. 程式人生 > >09 面向物件_多型&抽象類&介面

09 面向物件_多型&抽象類&介面

09.01_面向物件(多型的概述及其程式碼體現)

  • A:多型(polymorphic)概述
    • 事物存在的多種形態
  • B:多型前提
    • a:要有繼承關係。
    • b:要有方法重寫。
    • c:要有父類引用指向子類物件。
  • C:案例演示
    • 程式碼體現多型
class Demo1_Polymorphic {
	public static void main(String[] args) {
		Cat c = new Cat();
		c.eat();

		Animal a = new Cat();				//父類引用指向子類物件
		a.eat();  //貓吃魚
	}
}

class Animal {
	public void eat() {
		System.out.println("動物吃飯");
	}
}

class Cat extends Animal {
	public void eat() {  //方法重寫
		System.out.println("貓吃魚");
	}
}

09.02_面向物件(多型中的成員訪問特點之成員變數)

  • 成員變數
    • 編譯看左邊(父類),執行看左邊(父類)。 在這裡插入圖片描述 f.num輸出10,s.num輸出20

09.03_面向物件(多型中的成員訪問特點之成員方法)

  • 成員方法
    • 編譯看左邊(父類),執行看右邊(子類)。動態繫結 在這裡插入圖片描述

編譯的時候看父類中有沒有print方法,如果有,執行的時候執行的是子類中的print方法,如果沒有就會直接報錯

09.04_面向物件(多型中的成員訪問特點之靜態成員方法)

  • 靜態方法
    • 編譯看左邊(父類),執行看左邊(父類)。
    • (靜態和類相關,算不上重寫,所以,訪問還是左邊的)
    • 只有非靜態的成員方法,編譯看左邊,執行看右邊

09.05_面向物件(超人的故事)

  • A:案例分析
    • 通過該案例幫助學生理解多型的現象

09.06_面向物件(多型中向上轉型和向下轉型)

/*
		基本資料型別自動型別提升和強制型別轉換
		*/
		int i = 10;
		byte b = 20;
		//i = b;						//自動型別提升(小的提升為大的,byte型別2個位元組,int型別分配4個位元組)
		//b = (byte)i;					//強制型別轉換(精度降低)
  • A:案例演示
    • 詳細講解多型中向上轉型和向下轉型 Person p = new SuperMan();向上轉型 SuperMan sm = (SuperMan)p;向下轉型
class Demo3_SuperMan {
	public static void main(String[] args) {
		Person p = new SuperMan();			//父類引用指向子類物件,超人提升為了人
											//父類引用指向子類物件就是向上轉型
		System.out.println(p.name);
		p.談生意();
		SuperMan sm = (SuperMan)p;			//向下轉型
		sm.fly();
		//p.fly() 會出錯,父類中沒有,編譯時會出錯
		
		
	}
}

class Person {
	String name = "John";
	public void 談生意() {
		System.out.println("談生意");
	}
}

class SuperMan extends Person {
	String name = "superMan";

	public void 談生意() {
		System.out.println("談幾個億的大單子");
	}

	public void fly() {
		System.out.println("飛出去救人");
	}
}

向下轉型以後,p的地址直接複製給了sm

09.07_面向物件(多型的好處和弊端)

  • A:多型的好處
    • a:提高了程式碼的維護性(繼承保證)
    • b:提高了程式碼的擴充套件性(由多型保證)
  • B:案例演示
    • 多型的好處
    • 可以當作形式引數,可以接收任意子類物件
  • C:多型的弊端
    • 不能使用子類的特有屬性和行為
  • D:案例演示 method(Animal a) method(Cat c)
class Demo4_Animal {
	public static void main(String[] args) {
		method(new Cat());
		method(new Dog());

		//Animal a = new Cat();			開發的是很少在建立物件的時候用父類引用指向子類物件,
	                                    	//直接建立子類物件更方便,可以使用子類中的特有屬性和行為
	}
	
	//Cat c = new Dog();狗是一隻貓,這是錯誤的
	/*public static void method(Cat c) {			
		c.eat();
	}

	public static void method(Dog d) {
		d.eat();
	}*/
	
	//如果把狗強轉成貓就會出現型別轉換異常,ClassCastException
	public static void method(Animal a) {	//當作引數的時候用多型最好,因為擴充套件性強
		//關鍵字 instanceof 判斷前邊的引用是否是後邊的資料型別
		if (a instanceof Cat) {
			Cat c = (Cat)a;//如果要呼叫子類特有方法,需要強制型別轉換
			c.eat();
			c.catchMouse();
		}else if (a instanceof Dog) {
			Dog d = (Dog)a;
			d.eat();
			d.lookHome();
		}else {
			a.eat();
		}
	}
}

class Animal {
	public void eat() {
		System.out.println("動物吃飯");
	}
}

class Cat extends Animal {
	public void eat() {
		System.out.println("貓吃魚");
	}

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

class Dog extends Animal {
	public void eat() {
		System.out.println("狗吃肉");
	}

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

09.08_面向物件(多型中的題目分析題)

  • A:看下面程式是否有問題,如果沒有,說出結果
  •   class Fu {
      	public void show() {
      		System.out.println("fu show");
      	}
      }
    
      class Zi extends Fu {
      	public void show() {
      		System.out.println("zi show");
      	}
    
      	public void method() {
      		System.out.println("zi method");
      	}
      }
    
      class Test1Demo {
      	public static void main(String[] args) {
      		Fu f = new Zi();//編譯看左邊,執行看右邊
      		f.method();//編譯時出錯
      		f.show();//zi show
      	}
      }
    
  • B:看下面程式是否有問題,如果沒有,說出結果
  •   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("你");
      	}
      }
      public class Test2DuoTai {
      	public static void main(String[] args) {
      		A a = new B();//編譯看左邊有show方法則編譯通過,執行看右邊,執行子類中的show方法,
      		//此show方法時繼承父類的,父類中的show方法中有個show2方法呼叫的是子類的show2,故輸出“愛”
      		a.show();
      		
      		B b = new C();
      		b.show();
      	}
      }
    

09.09_面向物件(抽象類的概述及其特點)

  • A:抽象類概述
    • 抽象就是看不懂的
  • B:抽象類特點
    • a:抽象類和抽象方法必須用abstract關鍵字修飾
      • abstract class 類名 {}
      • public abstract void eat();//直接分號沒有大括號
    • b:抽象類不一定有抽象方法,有抽象方法的類一定是抽象類或者是介面
    • c:抽象類不能例項化那麼,抽象類如何例項化呢?
      • 按照多型的方式,由具體的子類例項化。其實這也是多型的一種,抽象類多型。(父類引用指向子類物件)
    • d:抽象類的子類
      • 要麼是抽象類
      • 要麼重寫抽象類中的所有抽象方法
class Demo1_Abstract {
	public static void main(String[] args) {
		//Animal a = new Animal();			//錯誤: Animal是抽象的; 無法例項化
		Animal a = new Cat();				//父類引用指向子類物件
		a.eat();
	}
}

abstract class Animal {						//抽象類
	public abstract void eat();				//抽象方法

	public Animal() {
		System.out.println("父類空參構造");
	}
}

class Cat extends Animal {
	public Cat() {
		super();
	}
	public void eat() {//重寫抽象類方法
		System.out.println("貓吃魚");
	}
}

09.10_面向物件(抽象類的成員特點)

  • A:抽象類的成員特點
    • a:成員變數:既可以是變數,也可以是常量。abstract是否可以修飾成員變數?不能修飾成員變數
    • b:構造方法:有。
      • 用於子類訪問父類資料的初始化。
    • c:成員方法:既可以是抽象的,也可以是非抽象的。
  • B:案例演示
    • 抽象類的成員特點
  • C:抽象類的成員方法特性:
    • a:抽象方法 強制要求子類做的事情。
    • b:非抽象方法 子類繼承的事情,提高程式碼複用性。

09.11_面向物件(葵花寶典)

  • 案例演示
    • 抽象類的作用

09.12_面向物件(抽象類練習貓狗案例)

  • A:案例演示
    • 具體事物:貓,狗
    • 共性:姓名,年齡,吃飯
    • 貓的特性:抓老鼠
    • 狗的特性:看家
public class Demo2_Dollection {
	public static void main(String[] args) {
		Cat c = new Cat("加菲", 8);
		System.out.println(c.getName() + ".." + c.getAge());
		c.eat();
		c.catchMouse();
		
		Dog d=new Dog("八公",30);
		System.out.println(d.getName() + ".." + d.getAge());
		d.eat();
		d.lookHome();
	}
}

abstract class Animal {
	private String name;
	private int age;

	public Animal() {
	}

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

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return this.age;
	}

	public abstract void eat();
}

class Cat extends Animal {
	public Cat() {
	}

	public Cat(String name, int age) {
		super(name, age);
	}

	public void eat() {
		System.out.println("貓吃魚");
	}

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

class Dog extends Animal {
	public Dog() {
	}

	public Dog(String name, int age) {
		super(name, age);
	}

	public void eat() {
		System.out.println("狗吃肉");
	}

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

09.13_面向物件(抽象類練習老師案例)

  • A:案例演示
    • 具體事物:基礎班老師,就業班老師
    • 共性:姓名,年齡,講課。
    • 具體事物:基礎班學生,就業班學生
    • 共性:姓名,年齡,學習

09.14_面向物件(抽象類練習員工案例)

  • A:案例演示
    • 假如我們在開發一個系統時需要對程式設計師類進行設計,程式設計師包含3個屬性:姓名、工號以及工資。
    • 經理,除了含有程式設計師的屬性外,另為還有一個獎金屬性。
    • 請使用繼承的思想設計出程式設計師類和經理類。要求類中提供必要的方法進行屬性訪問。
class Test3_Employee {
	public static void main(String[] args) {
		Coder c = new Coder("德瑪西亞","007",8000);
		c.work();

		Manager m = new Manager("蒼老師","9527",3000,20000);
		m.work();
	}
}

abstract class Employee {
	private String name;					//姓名
	private String id;						//工號
	private double salary;					//工資

	public Employee() {}					//空參構造

	public Employee(String name,String id,double salary) {
		this.name = name;
		this.id = id;
		this.salary = salary;
	}

	public void setName(String name) {		//設定姓名
		this.name = name;
	}

	public String getName() {				//獲取姓名
		return name;
	}

	public void setId(String id) {			//設定id
		this.id = id;
	}

	public String getId() {					//獲取id
		return id;
	}

	public void setSalary(double salary) {	//設定工資
		this.salary = salary;
	}

	public double getSalary() {				//獲取工資
		return salary;
	}

	public abstract void work();
}

//程式設計師
class Coder extends Employee {
	public Coder() {}					//空參構造

	public Coder(String name,String id,double salary) {
		super(name,id,salary);
	}

	public void work() {
		System.out.println("我的姓名是:" + this.getName() + ",我的工號是:" + this.getId() + ",我的工資是:" 
			+ this.getSalary() + ",我的工作內容是敲程式碼");
	}
}

//專案經理
class Manager extends Employee {
	private int bonus;					//獎金
	public Manager() {}					//空參構造

	public Manager(String name,String id,double salary,int bonus) {
		super(name,id,salary);
		this.bonus = bonus;
	}

	public void work() {
		System.out.println("我的姓名是:" + this.getName() + ",我的工號是:" + this.getId() + ",我的工資是:" 
			+ this.getSalary() + ",我的獎金是:" + bonus + ",我的工作內容是管理");
	}
}

09.15_面向物件(抽象類中的面試題)

  • A:面試題1
    • 一個抽象類如果沒有抽象方法,可不可以定義為抽象類?如果可以,有什麼意義?
    • 可以
    • 這麼做目的只有一個,就是不讓其他類建立本類物件,交給子類完成
  • B:面試題2
    • abstract不能和哪些關鍵字共存

不能與static共存,被abstract修飾的方法沒有方法體,被static修飾的可以用類名.呼叫,但是類名.呼叫抽象方法是沒有意義的 不能與final共存,被abstract修飾的方法強制讓子類重寫,final修飾的不讓子類重寫,矛盾 不能與private共存,被abstract修飾的是為了讓子類看到並強制重寫,被private修飾不讓子類訪問,矛盾

09.16_面向物件(介面的概述及其特點)

  • A:介面概述
    • 從狹義的角度講就是指java中的interface
    • 從廣義的角度講對外提供規則的都是介面
  • B:介面特點
    • a:介面用關鍵字interface表示
      • interface 介面名 {}
    • b:類實現介面用implements表示
      • class 類名 implements 介面名 {}
    • c:介面不能例項化
      • 那麼,介面如何例項化呢?
      • 按照多型的方式來例項化。
    • d:介面的子類
      • a:可以是抽象類。但是意義不大。
      • b:可以是具體類。要重寫介面中的所有抽象方法。(推薦方案)
  • C:案例演示
    • 介面特點
class Demo1_Interface {
	public static void main(String[] args) {
		//Inter i = new Inter();		//介面不能被例項化,因為呼叫抽象方法沒有意義
		Inter i = new Demo();			//父類引用指向子類物件
		i.print();
	}
}
interface Inter {
	public abstract void print();					//介面中的方法都是抽象的
}

class Demo implements Inter {
	public void print() {    //重寫介面中的抽象方法
		System.out.println("print");
	}
}

09.17_面向物件(介面的成員特點)

  • A:介面成員特點
    • 成員變數;只能是常量,並且是靜態(可以用介面名.常量)的並公共的。 * 預設修飾符:public static final //三個關鍵字可以互相交換位置 * 建議:自己手動給出。
    • 構造方法:介面沒有構造方法
    • 成員方法:只能是抽象方法(沒有方法體{})。 * 預設修飾符:public abstract * 建議:自己手動給出。
  • B:案例演示
    • 介面成員特點

一個類不寫繼承任何類,預設繼承Objedt類

09.18_面向物件(類與類,類與介面,介面與介面的關係)

  • A:類與類,類與介面,介面與介面的關係
    • a:類與類:
      • 繼承關係,只能單繼承,可以多層繼承。
    • b:類與介面:
      • 實現關係,可以單實現,也可以多實現。
      • 並且還可以在繼承一個類的同時實現多個介面。
    • c:介面與介面:
      • 繼承關係,可以單繼承,也可以多繼承。
  • B:案例演示
    • 類與類,類與介面,介面與介面的關係
interface InterA {
	public abstract void printA();
}

interface InterB {
	public abstract void printB();
}

interface InterC extends InterB,InterA {
}
//class Demo implements InterA,implements InterB {		//這麼做不允許是非法的
class Demo extends Object implements InterA,InterB {
	public void printA() {
		System.out.println("printA");
	}

	public void printB() {
		System.out.println("printB");
	}
}

09.19_面向物件(抽象類和介面的區別)

  • A:成員區別

    • 抽象類:
      • 成員變數:可以變數,也可以常量
      • 構造方法:有
      • 成員方法:可以抽象,也可以非抽象
    • 介面:
      • 成員變數:只可以常量
      • 成員方法:只可以抽象
  • B:關係區別

    • 類與類
      • 繼承,單繼承
    • 類與介面
      • 實現,單實現,多實現
    • 介面與介面
      • 繼承,單繼承,多繼承
  • C:設計理念區別

    • 抽象類 被繼承體現的是:”is a”的關係。抽象類中定義的是該繼承體系的共性功能。
    • 介面 被實現體現的是:”like a”的關係。介面中定義的是該繼承體系的擴充套件功能。

09.20_面向物件(貓狗案例加入跳高功能分析及其程式碼實現)

  • A:案例演示
    • 動物類:姓名,年齡,吃飯,睡覺。
    • 貓和狗
    • 動物培訓介面:跳高
class Test1_Animal {
	public static void main(String[] args) {
		Cat c = new Cat("加菲",8);
		c.eat();
		c.sleep();

		JumpCat jc = new JumpCat("跳高貓",3);
		jc.eat();
		jc.sleep();
		jc.jump();
	}
}
abstract class Animal {
	private String name;				//姓名
	private int age;					//年齡

	public Animal() {}					//空參構造

	public Animal(String name,int age) {//有參構造
		this.name = name;
		this.age = age;
	}

	public void setName(String name) {	//設定姓名
		this.name = name;
	}

	public String getName() {			//獲取姓名
		return name;
	}

	public void setAge(int age) {		//設定年齡
		this.age = age;
	}

	public int getAge() {				//獲取年齡
		return age;
	}

	public abstract void eat();			//吃飯

	public abstract void sleep();		//睡覺
}

interface Jumping {						//跳高的介面
	public void jump();
}

class Cat extends Animal {
	public Cat() {}					//空參構造

	public Cat(String name,int age) {//有參構造
		super(name,age);
	}

	public void eat() {
		System.out.println("貓吃魚");
	}

	public void sleep() {
		System.out.println("側著睡");
	}
}

class JumpCat extends Cat implements Jumping {
	public JumpCat() {}					//空參構造

	public JumpCat(String name,int age) {//有參構造
		super(name,age);
	}

	public void jump() {
		System.out.println("貓跳高");
	}
}