熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

面向對象思想之 -- 繼承以及多態

2022-06-13   來源: Java核心技術 

  在OOP簡介:理解類和對象這篇文章中我們討論了繼承和多態性的好處我們還粗略的學習了如何擴展基類定義子類繼承基類中合適的行為和屬性而重載那些並不適合的行為和屬性這種方式能夠削減代碼宏余以及錯誤的堆積
  
  現在我們將更深入的考察多重繼承性以及Java是如何處理它的我們還將通過學習動態綁定來學習多態性
  
  深入繼承性
  一些面向對象的語言提供叫做多重繼承的特點當一個對象需要從多於一個的基類繼承行為和屬性的時候這是有價值的多重繼承在有些情況下是復雜的例如假設我們需要定義一個基類Animal然後是Animal的兩個子類LandAnimal 和 WaterAnimal現在我們想要定義一個類來代表青蛙青蛙是兩棲動物所以我們自然會想到定義Frog類從LandAnimal和WaterAnimal類繼承這使得Frog類能夠同時從LandAnimal 和WaterAnimal類繼承所需的行為和屬性
  
  初看起來這是相當簡單的;但是讓我們為Animal添加一個叫做LivingEnvironment的屬性並用方法getLivingEnvironment來返回它我們假設LandAnimal 和 WaterAnimal類都重載了這個方法來實現特殊的功能LandAnimal將返回Land作為它的LivingEnvironment屬性的值而WaterAnimal將返回Water作為它的LivingEnvironment屬性的值現在當我們將Frog類作為LandAnimal 和 WaterAnimal 子類實現的時候想要得到Frog的LivingEnvironment屬性值這時將遇到一個麻煩:Frog類的getLivingEnvironment方法是返回Land值呢還是Water值?答案取決於編譯器如何處理多重繼承
  
  我在前面的文章裡就已經說過Java不支持多重繼承但它確實允許一個對象通過使用叫做接口的功能擁有多個特性下面的例子顯示了定義LandAnimal的接口的可能的定義代碼:
  public interface LandAnimal
  {
    public int getNumberOfLegs();
    public boolean hasATail();
  }
  
  一個使用接口的類在類定義語句的開始添加implements+接口名例如在Java中我們會以下面的方式定義Frog類:
  
  public class Frog extends Animal implements LandAnimal WaterAnimal
  
  接口並沒有什麼實際的功能;相反它的作用是聯系使用者和實現了這個接口的對象接口保證了對象實現接口定義的方法而且一個實現接口的對象能夠在運行時被強制轉換成接口類型例如使用上面的Frog定義並且假設LandAnimal類定義了一個叫做getNumberOfLegs的方法而WaterAnimal定義了一個叫做hasGills的方法那麼一個Frog類的實例可以在運行時被強制轉換成LandAnimal或WaterAnimal對象:
  
  Frog aFrog = new Frog();
  int legCount = ((LandAnimal)aFrog)getNumberOfLegs();
  Boolean gillFlag = ((WaterAnimal)aFrog)hasGills();
  
  注意Forg為什麼能夠被強制轉換成一個LandAnimal對象即使實際的LandAnimal對象並沒有被創建這使得我們能夠在運行時以其帶有的任何身份調用一個對象這就是所謂的動態綁定運行時綁定
  
  深入多態性
  Java使用動態綁定來使多態成為可能它指的是Java用來在運行時選擇調用的方法或對象的機制重載構成了了Java中的一種特殊的多態機制它表現在當一個類的兩個或者兩個以上的方法擁有相同的名字但是不同的參數列表或者說方法簽名一個方法的簽名指的是方法的名字以及參數的類型和數目類的每一個方法都有與之相關的唯一的簽名類可以有多個名字相同的方法只要它們的參數列表是唯一的例如我們能夠為Animal類定義兩個名字為getHello的方法用其中一個方法來獲得動物通常的叫聲而用另一個獲得當動物被驚嚇或是撫摩的時候的叫聲我們將給每一個方法唯一的簽名:
  
  public String getHello();
  public String getHello(int mood);
  
  現在讓我們修改例子程序來將我們討論的一些概念付諸實踐:
   
  public class HelloWorld
  {
  public static void main(String[] args)
  {
  Dog animal = new Dog();
  Cat animal = new Cat();
  Duck animal = new Duck();
  
  Systemoutprintln(A dog says +animalgetHello()
  + when scared says: +animalgetHello(AnimalSCARED)
  + is carnivorous: +animalisCarnivorous()
  + is a mammal: +animalisAMammal());
  Systemoutprintln(A cat says +animalgetHello()
  + when comforted says: +animalgetHello(AnimalCOMFORTED)
  + is carnivorous: +animalisCarnivorous()
  + is a mammal: +animalisAMammal());
  Systemoutprintln(A duck says +animalgetHello()
  + when scared says: +animalgetHello(AnimalSCARED)
  + is carnivorous: +animalisCarnivorous()
  + is a mammal: +animalisAMammal());
  }
  }
  
  abstract class Animal
  {
  public static final int SCARED = ;
  public static final int COMFORTED = ;
  
  public boolean isAMammal()
  {
  return(true);
  }
  
  public boolean isCarnivorous()
  {
  return(true);
  }
  
  abstract public String getHello();
  abstract public String getHello(int mood);
  }
  
  interface LandAnimal
  {
  public int getNumberOfLegs();
  public boolean hasATail();
  }
  
  interface WaterAnimal
  {
  public boolean hasGills();
  public boolean laysEggs();
  }
  
  class Dog extends Animal implements LandAnimal
  {
  // 重載父類的方法
  public String getHello()
  {
  return(Bark);
  }
  
  public String getHello(int mood)
  {
  switch (mood) {
  case SCARED:
  return(Growl);
  case COMFORTED:
  return();
  }
  
  return(Bark);
  }
  
  // LandAnimal 接口的實現
  public int getNumberOfLegs()
  {
  return();
  }
  
  public boolean hasATail()
  {
  return(true);
  }
  }
  
  class Cat extends Animal implements LandAnimal
  {
  // 重載父類的方法
  public String getHello()
  {
  return(Meow);
  }
  
  public String getHello(int mood)
  {
  switch (mood) {
  case SCARED:
  return(Hiss);
  case COMFORTED:
  return(Purr);
  }
  
  return(Meow);
  }
  
  // LandAnimal 接口實現
  public int getNumberOfLegs()
  {
  return();
  }
  
  public boolean hasATail()
  {
  return(true);
  }
  }
  
  class Duck extends Animal implements LandAnimal WaterAnimal
  {
  // 重載父類的方法
  public String getHello()
  {
  return(Quack);
  }
  
  public String getHello(int mood)
  {
  switch (mood) {
  case SCARED:
  return(Quack Quack Quack);
  case COMFORTED:
  return();
  }
  
  return(Quack);
  }
  
  public boolean isAMammal()
  {
  return(false);
  }
  
  public boolean isCarnivorous()
  {
  return(false);
  }
  
  // WaterAnimal 接口實現
  public boolean hasGills()
  {
  return(false);
  }
  
  public boolean laysEggs()
  {
  return(true);
  }
  
  // LandAnimal 接口實現
  public int getNumberOfLegs()
  {
  return();
  }
  
  public boolean hasATail()
  {
  return(false);
  }
  }
  
  程序執行後輸出的結果如下:
  
  A dog says Bark when scared says: Growl is carnivorous: true is a mammal: true
  A cat says Meow when comforted says: Purr is carnivorous: true is a mammal: true
  A duck says Quack when scared says: Quack Quack Quack is carnivorous: false is a mammal: false
  
  總結
  綜合繼承多態和接口的概念提供了一組強大的編程工具允許我們重用代碼隔離錯誤的發生並獲得動態/運行時綁定帶來的好處在下一篇文章裡我們將討論如何使用Java的變量作用域/可見域規則來控制方法和屬性的暴露問題
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26843.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.