多态性与重写与重载

时间:2008-09-30 19:29:02

标签: java oop polymorphism overloading override

就Java而言,当有人问:

  

什么是多态?

重载覆盖会成为可接受的答案吗?

我认为还有更多的东西。

如果您有一个抽象基类定义了一个没有实现的方法,并且您在子类中定义了该方法,那还是会覆盖吗?

我认为重载肯定不是正确答案。

21 个答案:

答案 0 :(得分:871)

表达多态性的最清晰方式是通过抽象基类(或接口)

public abstract class Human{
   ...
   public abstract void goPee();
}

这个类是抽象的,因为goPee()方法不适用于人类。它只适用于男性和女性的子类。此外,人类是一个抽象的概念 - 你不能创造一个既不是男性也不是女性的人。它必须是一个或另一个。

所以我们通过使用抽象类来推迟实现。

public class Male extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Stand Up");
    }
}

public class Female extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Sit Down");
    }
}

现在我们可以告诉整个房间里满是人类去撒尿。

public static void main(String[] args){
    ArrayList<Human> group = new ArrayList<Human>();
    group.add(new Male());
    group.add(new Female());
    // ... add more...

    // tell the class to take a pee break
    for (Human person : group) person.goPee();
}

运行它会产生:

Stand Up
Sit Down
...

答案 1 :(得分:91)

多态性是类实例的行为能力,就好像它是其继承树中另一个类的实例,通常是其祖先类之一。例如,在Java中,所有类都继承自Object。因此,您可以创建一个Object类型的变量,并为其分配任何类的实例。

覆盖是一种函数,它发生在继承自另一个类的类中。覆盖函数“替换”从基类继承的函数,但这样做的方式是,即使它的类的实例假装通过多态而成为不同的类型,也会调用它。参考前面的示例,您可以定义自己的类并覆盖toString()函数。因为此函数是从Object继承的,所以如果将此类的实例复制到Object类型变量中,它仍然可用。通常,如果在假装是Object时调用类上的toString(),实际触发的toString版本就是在Object本身定义的版本。但是,因为函数是覆盖,所以即使类实例的真实类型隐藏在多态性之后,也会使用类中toString()的定义。

重载是定义具有相同名称但具有不同参数的多个方法的操作。它与重写或多态无关。

答案 2 :(得分:43)

多态性是指多种形式,同一对象根据需要执行不同的操作。

多态性可以通过两种方式实现,即

  1. 方法覆盖
  2. 方法重载
  3. 方法重载意味着使用相同的方法名称在同一个类中编写两个或多个方法,但传递的参数不同。

    方法覆盖意味着我们在不同的类中使用方法名称,这意味着在子类中使用了父类方法。

    在Java中实现多态,超类引用变量可以保存子类对象。

    要实现多态,每个开发人员必须在项目中使用相同的方法名称。

答案 3 :(得分:43)

以下是伪C#/ Java中的多态性示例:

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

Main函数不知道动物的类型,并且取决于MakeNoise()方法的特定实现的行为。

编辑:看起来Brian打败了我。有趣的是我们使用相同的例子。但上述代码应该有助于澄清这些概念。

答案 4 :(得分:39)

覆盖和重载都用于实现多态性。

你可以在课堂上有一个方法     在一个或中重写     更多的子类。该方法     不同的东西取决于哪个     class用于实例化一个对象。

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

    class Coffee extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature > 70;
       }
    }

    class Wine extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature < 10;
       }
    }

你也可以有一个方法     重载,包含两组或更多组参数。该方法     基于的不同的东西     通过的论证类型。

    class Server {
        public void pour (Coffee liquid) {
            new Cup().fillToTopWith(liquid);
        }

        public void pour (Wine liquid) {
            new WineGlass().fillHalfwayWith(liquid);
        }

        public void pour (Lemonade liquid, boolean ice) {
            Glass glass = new Glass();
            if (ice) {
                glass.fillToTopWith(new Ice());
            }
            glass.fillToTopWith(liquid);
        }
    }

答案 5 :(得分:13)

你知道重载不是答案。

两者都没有超越。覆盖是获得多态性的手段。多态性是对象根据其类型改变行为的能力。当展示多态性的对象的调用者不知道该对象的特定类型时,最好地证明这一点。

答案 6 :(得分:10)

具体说超载或覆盖不能全面展示。多态性只是一个对象根据其类型专门化其行为的能力。

我不同意这里的一些答案,因为在具有相同名称的方法可以表现不同的情况下,重载是多态(参数多态)的一种形式,给出不同的参数类型。一个很好的例子是运算符重载。您可以定义“+”以接受不同类型的参数 - 比如字符串或int - 并且基于这些类型,“+”将表现不同。

多态性还包括继承和重写方法,尽管它们可以是基本类型中的抽象或虚拟。就基于继承的多态性而言,Java仅支持单类继承,将其多态行为限制为单个基类型链的行为。 Java确实支持多接口的实现,这是多态行为的另一种形式。

答案 7 :(得分:7)

多态性只是意味着“多种形式”。

它不需要继承来实现...因为接口实现根本不是继承,它满足多态需求。可以说,接口实现为继承提供了“更好”的多态需求。

例如,你会创建一个超类来描述所有可以飞行的东西吗?我不应该想。您最好能够创建一个描述航班的界面并将其留在那里。

因此,由于接口描述了行为,并且方法名称描述了行为(对于程序员),因此将方法重载视为较小形式的多态性并不是一件容易的事。

答案 8 :(得分:6)

经典的例子,狗和猫是动物,动物有makeNoise的方法。我可以遍历一系列动物,在它们上面调用makeNoise,并期望它们可以在那里进行各自的实现。

调用代码不必知道它们是什么特定的动物。

这就是我认为的多态性。

答案 9 :(得分:4)

既不:

重载是指具有不同参数的相同函数名称。

覆盖是指子类用自己的方法替换父方法(这在迭代中不构成多态)。

多态性是晚期结合,例如正在调用基类(父)方法,但直到运行时,应用程序才知道实际对象是什么 - 它可能是一个子类,其方法不同。这是因为任何子类都可以在定义基类的地方使用。

在Java中,您会看到集合库中的多态性:

int countStuff(List stuff) {
  return stuff.size();
}

List是基类,如果你计算链表,向量,数组或自定义列表实现,编译器就没有线索,只要它像List一样:

List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);

如果你超负荷,你就有:

int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...

并且编译器将选择正确版本的countStuff()以匹配参数。

答案 10 :(得分:4)

多态性是对象以多种形式出现的能力。这涉及使用继承和虚函数来构建可以互换的对象族。基类包含虚函数的原型,可能是未实现的,或者是应用程序所指示的默认实现,而各种派生类每个都以不同的方式实现它们以影响不同的行为。

答案 11 :(得分:3)

术语重载是指具有相同名称的多个版本,通常是具有不同参数列表的方法

public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }

因此,这些函数可能会执行相同的操作,但您可以选择使用ID或名称来调用它。与继承,抽象类等无关。

覆盖通常是指多态性,正如您在问题中描述的那样

答案 12 :(得分:2)

我认为你们正在混合概念。 多态性是对象在运行时表现不同的能力。为实现这一目标,您需要两个必要条件:

  1. 晚期绑定
  2. 继承。
  3. 说过重载意味着与覆盖不同,具体取决于您使用的语言。例如,在Java中不存在覆盖重载子类中提供了对其基类具有不同签名的重载方法。否则它们将被覆盖(请注意,我的意思是现在无法从对象外部调用基类方法。)

    但是在C ++中并非如此。任何重载方法,无论签名是否相同(不同数量,不同类型),重写也是如此。到目前为止,当从子类对象外部调用时,子类的方法在子类中不再可用,显然。

    所以答案是在谈论Java使用重载时。在任何其他语言中可能会有所不同,因为它发生在c ++

答案 13 :(得分:2)

重载是指定义2个具有相同名称但参数不同的方法

overriding是通过子类中具有相同名称的函数更改基类行为的地方。

因此,多态性与覆盖有关,但并非真正超载。

然而,如果有人给我一个简单的回答“覆盖”问题“什么是多态?”我会要求进一步解释。

答案 14 :(得分:2)

覆盖更像是通过声明与上层方法(超级方法)具有相同名称和签名的方法来隐藏继承方法,这会向类添加多态行为。 换句话说,选择要调用的级别方法的决定将在运行时而不是在编译时进行。 这导致了界面和实现的概念。

答案 15 :(得分:2)

  

什么是多态?

来自java tutorial

多态性的字典定义是指生物学中的原理,其中生物体或物种可以具有许多不同的形式或阶段。这个原则也可以应用于面向对象的编程和Java语言之类的语言。 类的子类可以定义自己的独特行为,但可以共享父类的一些相同功能。

通过考虑示例和定义,应接受 重写

关于你的第二个问题:

  

如果你有一个抽象基类定义了一个没有实现的方法,并且你在子类中定义了那个方法,那还是会覆盖吗?

应该称为覆盖。

查看此示例以了解不同类型的覆盖。

  1. 基类不提供实现,子类必须覆盖完整方法 - (摘要)
  2. 基类提供默认实现,子类可以改变行为
  3. 通过调用super.methodName()作为第一个语句
  4. ,子类为基类实现添加了扩展
  5. 基类定义算法的结构(模板方法),子类将覆盖算法的一部分
  6. 代码段:

    import java.util.HashMap;
    
    abstract class Game implements Runnable{
    
        protected boolean runGame = true;
        protected Player player1 = null;
        protected Player player2 = null;
        protected Player currentPlayer = null;
    
        public Game(){
            player1 = new Player("Player 1");
            player2 = new Player("Player 2");
            currentPlayer = player1;
            initializeGame();
        }
    
        /* Type 1: Let subclass define own implementation. Base class defines abstract method to force
            sub-classes to define implementation    
        */
    
        protected abstract void initializeGame();
    
        /* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
        protected void logTimeBetweenMoves(Player player){
            System.out.println("Base class: Move Duration: player.PlayerActTime - player.MoveShownTime");
        }
    
        /* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by calling
            super.methodName() in first line of the child class method and specific implementation later */
        protected void logGameStatistics(){
            System.out.println("Base class: logGameStatistics:");
        }
        /* Type 4: Template method: Structure of base class can't be changed but sub-class can some part of behaviour */
        protected void runGame() throws Exception{
            System.out.println("Base class: Defining the flow for Game:");  
            while ( runGame) {
                /*
                1. Set current player
                2. Get Player Move
                */
                validatePlayerMove(currentPlayer);  
                logTimeBetweenMoves(currentPlayer);
                Thread.sleep(500);
                setNextPlayer();
            }
            logGameStatistics();
        }
        /* sub-part of the template method, which define child class behaviour */
        protected abstract void validatePlayerMove(Player p);
    
        protected void setRunGame(boolean status){
            this.runGame = status;
        }
        public void setCurrentPlayer(Player p){
            this.currentPlayer = p;
        }
        public void setNextPlayer(){
            if ( currentPlayer == player1) {
                currentPlayer = player2;
            }else{
                currentPlayer = player1;
            }
        }
        public void run(){
            try{
                runGame();
            }catch(Exception err){
                err.printStackTrace();
            }
        }
    }
    
    class Player{
        String name;
        Player(String name){
            this.name = name;
        }
        public String getName(){
            return name;
        }
    }
    
    /* Concrete Game implementation  */
    class Chess extends Game{
        public Chess(){
            super();
        }
        public void initializeGame(){
            System.out.println("Child class: Initialized Chess game");
        }
        protected void validatePlayerMove(Player p){
            System.out.println("Child class: Validate Chess move:"+p.getName());
        }
        protected void logGameStatistics(){
            super.logGameStatistics();
            System.out.println("Child class: Add Chess specific logGameStatistics:");
        }
    }
    class TicTacToe extends Game{
        public TicTacToe(){
            super();
        }
        public void initializeGame(){
            System.out.println("Child class: Initialized TicTacToe game");
        }
        protected void validatePlayerMove(Player p){
            System.out.println("Child class: Validate TicTacToe move:"+p.getName());
        }
    }
    
    public class Polymorphism{
        public static void main(String args[]){
            try{
    
                Game game = new Chess();
                Thread t1 = new Thread(game);
                t1.start();
                Thread.sleep(1000);
                game.setRunGame(false);
                Thread.sleep(1000);
    
                game = new TicTacToe();
                Thread t2 = new Thread(game);
                t2.start();
                Thread.sleep(1000);
                game.setRunGame(false);
    
            }catch(Exception err){
                err.printStackTrace();
            }       
        }
    }
    

    输出:

    Child class: Initialized Chess game
    Base class: Defining the flow for Game:
    Child class: Validate Chess move:Player 1
    Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
    Child class: Validate Chess move:Player 2
    Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
    Base class: logGameStatistics:
    Child class: Add Chess specific logGameStatistics:
    Child class: Initialized TicTacToe game
    Base class: Defining the flow for Game:
    Child class: Validate TicTacToe move:Player 1
    Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
    Child class: Validate TicTacToe move:Player 2
    Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
    Base class: logGameStatistics:
    

答案 16 :(得分:2)

尽管在这篇文章中已经详细解释了多态性,但我想更多地强调其中的一部分。

  

为什么多态性在任何OOP语言中都如此重要。

让我们尝试为具有和不具有继承/多态性的电视构建一个简单的应用程序。发布每个版本的应用程序,我们做一个小型的回顾。

假设您是电视公司的软件工程师,并且要求您编写音量,亮度和颜色控制器软件,以增加和减少用户命令的值。

首先,通过添加

为每个功能编写类
  1. set: - 设置控制器的值。(假设这有控制器特定的代码)
  2. get: - 获取控制器的值。(假设这有控制器特定的代码)
  3. 调整: - 验证输入并设置控制器。(通用验证...独立于控制器)
  4. 使用控制器的用户输入映射: - 获取用户输入并相应地调用控制器。
  5.   

    应用版本1

    import java.util.Scanner;    
    class VolumeControllerV1 {
        private int value;
        int get()    {
            return value;
        }
        void set(int value) {
            System.out.println("Old value of VolumeController \t"+this.value);
            this.value = value;
            System.out.println("New value of VolumeController \t"+this.value);
        }
        void adjust(int value)  {
            int temp = this.get();
            if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
                System.out.println("Can not adjust any further");
                return;
            }
            this.set(temp + value);
        }
    }
    class  BrightnessControllerV1 {
        private int value;
        int get()    {
            return value;
        }
        void set(int value) {
            System.out.println("Old value of BrightnessController \t"+this.value);
            this.value = value;
            System.out.println("New value of BrightnessController \t"+this.value);
        }
        void adjust(int value)  {
            int temp = this.get();
            if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
                System.out.println("Can not adjust any further");
                return;
            }
            this.set(temp + value);
        }
    }
    class ColourControllerV1    {
        private int value;
        int get()    {
            return value;
        }
        void set(int value) {
            System.out.println("Old value of ColourController \t"+this.value);
            this.value = value;
            System.out.println("New value of ColourController \t"+this.value);
        }
        void adjust(int value)  {
            int temp = this.get();
            if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
                System.out.println("Can not adjust any further");
                return;
            }
            this.set(temp + value);
        }
    }
    
    /*
     *       There can be n number of controllers
     * */
    public class TvApplicationV1 {
        public static void main(String[] args)  {
            VolumeControllerV1 volumeControllerV1 = new VolumeControllerV1();
            BrightnessControllerV1 brightnessControllerV1 = new BrightnessControllerV1();
            ColourControllerV1 colourControllerV1 = new ColourControllerV1();
    
    
            OUTER: while(true) {
                Scanner sc=new Scanner(System.in);
                System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
                System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
                System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
                System.out.println("Press any other Button to shutdown");
                int button = sc.nextInt();
                switch (button) {
                    case  1:    {
                        volumeControllerV1.adjust(5);
                        break;
                    }
                    case 2: {
                        volumeControllerV1.adjust(-5);
                        break;
                    }
                    case  3:    {
                        brightnessControllerV1.adjust(5);
                        break;
                    }
                    case 4: {
                        brightnessControllerV1.adjust(-5);
                        break;
                    }
                    case  5:    {
                        colourControllerV1.adjust(5);
                        break;
                    }
                    case 6: {
                    colourControllerV1.adjust(-5);
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }
    
        }
        }
    }
    

    现在,您已准备好部署我们的第一个工作应用程序版本。是时候分析迄今所做的工作了。

      

    电视应用版本1中的问题

    1. 调整(int值)代码在所有三个类中都是重复的。您希望最小化代码的两面性。 (但你没有考虑常用代码并将其移至某些超级类以避免重复代码)
    2. 只要您的应用程序按预期工作,您就决定使用它。

        

      有时,您的Boss会回复您并要求您向现有应用程序添加重置功能。重置会将所有3个三个控制器设置为各自的默认值。

      您开始为新功能编写新类(ResetFunctionV2)并映射此新功能的用户输入映射代码。

        

      应用程序版本2

      import java.util.Scanner;
      class VolumeControllerV2    {
      
          private int defaultValue = 25;
          private int value;
      
          int getDefaultValue() {
              return defaultValue;
          }
          int get()    {
              return value;
          }
          void set(int value) {
              System.out.println("Old value of VolumeController \t"+this.value);
              this.value = value;
              System.out.println("New value of VolumeController \t"+this.value);
          }
          void adjust(int value)  {
              int temp = this.get();
              if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
                  System.out.println("Can not adjust any further");
                  return;
              }
              this.set(temp + value);
          }
      }
      class  BrightnessControllerV2   {
      
          private int defaultValue = 50;
          private int value;
          int get()    {
              return value;
          }
          int getDefaultValue() {
              return defaultValue;
          }
          void set(int value) {
              System.out.println("Old value of BrightnessController \t"+this.value);
              this.value = value;
              System.out.println("New value of BrightnessController \t"+this.value);
          }
          void adjust(int value)  {
              int temp = this.get();
              if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
                  System.out.println("Can not adjust any further");
                  return;
              }
              this.set(temp + value);
          }
      }
      class ColourControllerV2    {
      
          private int defaultValue = 40;
          private int value;
          int get()    {
              return value;
          }
          int getDefaultValue() {
              return defaultValue;
          }
          void set(int value) {
              System.out.println("Old value of ColourController \t"+this.value);
              this.value = value;
              System.out.println("New value of ColourController \t"+this.value);
          }
          void adjust(int value)  {
              int temp = this.get();
              if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
                  System.out.println("Can not adjust any further");
                  return;
              }
              this.set(temp + value);
          }
      }
      
      class ResetFunctionV2 {
      
          private VolumeControllerV2 volumeControllerV2 ;
          private BrightnessControllerV2 brightnessControllerV2;
          private ColourControllerV2 colourControllerV2;
      
          ResetFunctionV2(VolumeControllerV2 volumeControllerV2, BrightnessControllerV2 brightnessControllerV2, ColourControllerV2 colourControllerV2)  {
              this.volumeControllerV2 = volumeControllerV2;
              this.brightnessControllerV2 = brightnessControllerV2;
              this.colourControllerV2 = colourControllerV2;
          }
          void onReset()    {
              volumeControllerV2.set(volumeControllerV2.getDefaultValue());
              brightnessControllerV2.set(brightnessControllerV2.getDefaultValue());
              colourControllerV2.set(colourControllerV2.getDefaultValue());
          }
      }
      /*
       *       so on
       *       There can be n number of controllers
       *
       * */
      public class TvApplicationV2 {
          public static void main(String[] args)  {
              VolumeControllerV2 volumeControllerV2 = new VolumeControllerV2();
              BrightnessControllerV2 brightnessControllerV2 = new BrightnessControllerV2();
              ColourControllerV2 colourControllerV2 = new ColourControllerV2();
      
              ResetFunctionV2 resetFunctionV2 = new ResetFunctionV2(volumeControllerV2, brightnessControllerV2, colourControllerV2);
      
              OUTER: while(true) {
                  Scanner sc=new Scanner(System.in);
                  System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
                  System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
                  System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
                  System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
                  int button = sc.nextInt();
                  switch (button) {
                      case  1:    {
                          volumeControllerV2.adjust(5);
                          break;
                      }
                      case 2: {
                          volumeControllerV2.adjust(-5);
                          break;
                      }
                      case  3:    {
                          brightnessControllerV2.adjust(5);
                          break;
                      }
                      case 4: {
                          brightnessControllerV2.adjust(-5);
                          break;
                      }
                      case  5:    {
                          colourControllerV2.adjust(5);
                          break;
                      }
                      case 6: {
                          colourControllerV2.adjust(-5);
                          break;
                      }
                      case 7: {
                          resetFunctionV2.onReset();
                          break;
                      }
                      default:
                          System.out.println("Shutting down...........");
                          break OUTER;
                  }
      
              }
          }
      }
      

      因此,您可以使用重置功能准备好应用程序。但是,现在你开始意识到了

        

      电视应用第2版中的问题

      1. 如果产品引入了新控制器,则必须更改重置功能代码。
      2. 如果控制器的数量增长很多,那么在保存控制器的引用时会遇到问题。
      3. 重置功能代码与所有控制器类的代码紧密耦合(获取和设置默认值)。
      4. 重置要素类(ResetFunctionV2)可以访问Controller类的其他方法(调整),这是不合需要的。
      5.   

        与此同时,您听到Boss说您可能需要添加一项功能,其中每个控制器在启动时都需要通过互联网从公司的托管驱动程序库中检查最新版本的驱动程序。

        现在你开始认为,如果你没有重新考虑你的应用程序,那么这个要添加的新功能类似于重置功能和应用程序问题(V2)将成倍增加。

        您开始考虑使用继承,以便您可以利用JAVA的多态性并添加新的抽象类(ControllerV3)到

        1. 声明get和set方法的签名。
        2. 包含之前在所有控制器中复制的adjust方法实现。
        3. 声明setDefault方法,以便利用多态性轻松实现重置功能。<​​/ li>

          通过这些改进,您可以随时使用电视应用程序的第3版。

            

          应用程序版本3

          import java.util.ArrayList;
          import java.util.List;
          import java.util.Scanner;
          
          abstract class ControllerV3 {
              abstract void set(int value);
              abstract int get();
              void adjust(int value)  {
                  int temp = this.get();
                  if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
                      System.out.println("Can not adjust any further");
                      return;
                  }
                  this.set(temp + value);
              }
              abstract void setDefault();
          }
          class VolumeControllerV3 extends ControllerV3   {
          
              private int defaultValue = 25;
              private int value;
          
              public void setDefault() {
                  set(defaultValue);
              }
              int get()    {
                  return value;
              }
              void set(int value) {
                  System.out.println("Old value of VolumeController \t"+this.value);
                  this.value = value;
                  System.out.println("New value of VolumeController \t"+this.value);
              }
          }
          class  BrightnessControllerV3  extends ControllerV3   {
          
              private int defaultValue = 50;
              private int value;
          
              public void setDefault() {
                  set(defaultValue);
              }
              int get()    {
                  return value;
              }
              void set(int value) {
                  System.out.println("Old value of BrightnessController \t"+this.value);
                  this.value = value;
                  System.out.println("New value of BrightnessController \t"+this.value);
              }
          }
          class ColourControllerV3 extends ControllerV3   {
          
              private int defaultValue = 40;
              private int value;
          
              public void setDefault() {
                  set(defaultValue);
              }
              int get()    {
                  return value;
              }
              void set(int value) {
                  System.out.println("Old value of ColourController \t"+this.value);
                  this.value = value;
                  System.out.println("New value of ColourController \t"+this.value);
              }
          }
          
          class ResetFunctionV3 {
          
              private List<ControllerV3> controllers = null;
          
              ResetFunctionV3(List<ControllerV3> controllers)  {
                  this.controllers = controllers;
              }
              void onReset()    {
                  for (ControllerV3 controllerV3 :this.controllers)  {
                      controllerV3.setDefault();
                  }
              }
          }
          /*
           *       so on
           *       There can be n number of controllers
           *
           * */
          public class TvApplicationV3 {
              public static void main(String[] args)  {
                  VolumeControllerV3 volumeControllerV3 = new VolumeControllerV3();
                  BrightnessControllerV3 brightnessControllerV3 = new BrightnessControllerV3();
                  ColourControllerV3 colourControllerV3 = new ColourControllerV3();
          
                  List<ControllerV3> controllerV3s = new ArrayList<>();
                  controllerV3s.add(volumeControllerV3);
                  controllerV3s.add(brightnessControllerV3);
                  controllerV3s.add(colourControllerV3);
          
                  ResetFunctionV3 resetFunctionV3 = new ResetFunctionV3(controllerV3s);
          
                  OUTER: while(true) {
                      Scanner sc=new Scanner(System.in);
                      System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
                      System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
                      System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
                      System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
                      int button = sc.nextInt();
                      switch (button) {
                          case  1:    {
                              volumeControllerV3.adjust(5);
                              break;
                          }
                          case 2: {
                              volumeControllerV3.adjust(-5);
                              break;
                          }
                          case  3:    {
                              brightnessControllerV3.adjust(5);
                              break;
                          }
                          case 4: {
                              brightnessControllerV3.adjust(-5);
                              break;
                          }
                          case  5:    {
                              colourControllerV3.adjust(5);
                              break;
                          }
                          case 6: {
                              colourControllerV3.adjust(-5);
                              break;
                          }
                          case 7: {
                              resetFunctionV3.onReset();
                              break;
                          }
                          default:
                              System.out.println("Shutting down...........");
                              break OUTER;
                      }
          
                  }
              }
          }
          

          虽然V2的问题列表中列出的大部分问题都已解决,但

          除外
            

          电视应用第3版中的问题

          1. 重置要素类(ResetFunctionV3)可以访问Controller类的其他方法(调整),这是不可取的。
          2. 同样,您考虑解决此问题,因为现在您还可以实现另一个功能(启动时更新驱动程序)。如果您不修复它,它也会被复制到新功能。

            所以你划分抽象类中定义的契约并为

            编写2个接口
            1. 重置功能。<​​/ li>
            2. 驱动程序更新。
            3. 让你的第一个具体课程实现如下

                

              应用程序版本4

              import java.util.ArrayList;
              import java.util.List;
              import java.util.Scanner;
              
              interface OnReset {
                  void setDefault();
              }
              interface OnStart {
                  void checkForDriverUpdate();
              }
              abstract class ControllerV4 implements OnReset,OnStart {
                  abstract void set(int value);
                  abstract int get();
                  void adjust(int value)  {
                      int temp = this.get();
                      if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
                          System.out.println("Can not adjust any further");
                          return;
                      }
                      this.set(temp + value);
                  }
              }
              
              class VolumeControllerV4 extends ControllerV4 {
              
                  private int defaultValue = 25;
                  private int value;
                  @Override
                  int get()    {
                      return value;
                  }
                  void set(int value) {
                      System.out.println("Old value of VolumeController \t"+this.value);
                      this.value = value;
                      System.out.println("New value of VolumeController \t"+this.value);
                  }
                  @Override
                  public void setDefault() {
                      set(defaultValue);
                  }
              
                  @Override
                  public void checkForDriverUpdate()    {
                      System.out.println("Checking driver update for VolumeController .... Done");
                  }
              }
              class  BrightnessControllerV4 extends ControllerV4 {
              
                  private int defaultValue = 50;
                  private int value;
                  @Override
                  int get()    {
                      return value;
                  }
                  @Override
                  void set(int value) {
                      System.out.println("Old value of BrightnessController \t"+this.value);
                      this.value = value;
                      System.out.println("New value of BrightnessController \t"+this.value);
                  }
              
                  @Override
                  public void setDefault() {
                      set(defaultValue);
                  }
              
                  @Override
                  public void checkForDriverUpdate()    {
                      System.out.println("Checking driver update for BrightnessController .... Done");
                  }
              }
              class ColourControllerV4 extends ControllerV4 {
              
                  private int defaultValue = 40;
                  private int value;
                  @Override
                  int get()    {
                      return value;
                  }
                  void set(int value) {
                      System.out.println("Old value of ColourController \t"+this.value);
                      this.value = value;
                      System.out.println("New value of ColourController \t"+this.value);
                  }
                  @Override
                  public void setDefault() {
                      set(defaultValue);
                  }
              
                  @Override
                  public void checkForDriverUpdate()    {
                      System.out.println("Checking driver update for ColourController .... Done");
                  }
              }
              class ResetFunctionV4 {
              
                  private List<OnReset> controllers = null;
              
                  ResetFunctionV4(List<OnReset> controllers)  {
                      this.controllers = controllers;
                  }
                  void onReset()    {
                      for (OnReset onreset :this.controllers)  {
                          onreset.setDefault();
                      }
                  }
              }
              class InitializeDeviceV4 {
              
                  private List<OnStart> controllers = null;
              
                  InitializeDeviceV4(List<OnStart> controllers)  {
                      this.controllers = controllers;
                  }
                  void initialize()    {
                      for (OnStart onStart :this.controllers)  {
                          onStart.checkForDriverUpdate();
                      }
                  }
              }
              /*
              *       so on
              *       There can be n number of controllers
              *
              * */
              public class TvApplicationV4 {
                  public static void main(String[] args)  {
                      VolumeControllerV4 volumeControllerV4 = new VolumeControllerV4();
                      BrightnessControllerV4 brightnessControllerV4 = new BrightnessControllerV4();
                      ColourControllerV4 colourControllerV4 = new ColourControllerV4();
                      List<ControllerV4> controllerV4s = new ArrayList<>();
                      controllerV4s.add(brightnessControllerV4);
                      controllerV4s.add(volumeControllerV4);
                      controllerV4s.add(colourControllerV4);
              
                      List<OnStart> controllersToInitialize = new ArrayList<>();
                      controllersToInitialize.addAll(controllerV4s);
                      InitializeDeviceV4 initializeDeviceV4 = new InitializeDeviceV4(controllersToInitialize);
                      initializeDeviceV4.initialize();
              
                      List<OnReset> controllersToReset = new ArrayList<>();
                      controllersToReset.addAll(controllerV4s);
                      ResetFunctionV4 resetFunctionV4 = new ResetFunctionV4(controllersToReset);
              
                      OUTER: while(true) {
                          Scanner sc=new Scanner(System.in);
                          System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
                          System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
                          System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
                          System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
                          int button = sc.nextInt();
                          switch (button) {
                              case  1:    {
                                  volumeControllerV4.adjust(5);
                                  break;
                              }
                              case 2: {
                                  volumeControllerV4.adjust(-5);
                                  break;
                              }
                              case  3:    {
                                  brightnessControllerV4.adjust(5);
                                  break;
                              }
                              case 4: {
                                  brightnessControllerV4.adjust(-5);
                                  break;
                              }
                              case  5:    {
                                  colourControllerV4.adjust(5);
                                  break;
                              }
                              case 6: {
                                  colourControllerV4.adjust(-5);
                                  break;
                              }
                              case 7: {
                                  resetFunctionV4.onReset();
                                  break;
                              }
                              default:
                                  System.out.println("Shutting down...........");
                                  break OUTER;
                          }
              
                      }
                  }
              }
              
                

              现在你面临的所有问题都得到了解决,你意识到通过使用继承和多态,你可以

              1. 保持应用程序的各个部分松散耦合。(重置或驱动程序更新功能组件不需要了解实际的控制器类别(音量,亮度和颜色),任何实现OnReset或OnStart的类都可以接受重置或驱动程序更新功能组件分别)。
              2. 应用程序增强变得更容易。(新增的控制器不会影响重置或驱动程序更新功能组件,现在您可以轻松添加新的功能)
              3. 保持抽象层。(现在重置功能只能看到控制器的setDefault方法和重置功能只能看到控制器的checkForDriverUpdate方法)
              4. 希望,这有助于: - )

答案 17 :(得分:1)

多态性更可能是因为意味着涉及到...在java中的OVERRIDING

所有关于SAME对象在不同情况下的不同行为(编程方式......你可以调用不同的ARGUMENTS)

我认为以下示例将帮助您理解......虽然它不是纯粹的Java代码......

     public void See(Friend)
     {
        System.out.println("Talk");
     }

但如果我们更改ARGUMENT ......行为将会改变......

     public void See(Enemy)
     {
        System.out.println("Run");
     }

人(这里是“对象”)是相同的......

答案 18 :(得分:1)

多态性是对象的多个实现,或者您可以说对象的多种形式。假设你有一个类Animals作为抽象基类,它有一个名为movement()的方法,它定义了动物移动的方式。现在实际上我们有不同种类的动物,它们的移动也不同,其中一些有两条腿,有些有4条腿,有些没有腿等等。为了定义地球上每种动物的不同movement(),我们需要应用多态性。但是,您需要定义更多类,即类Dogs Cats Fish等。然后,您需要从基类Animals扩展这些类并覆盖其方法{{1基于每只动物的新动作功能。您也可以使用movement()来实现这一目标。这里的关键字是重写,重载是不同的,不被视为多态。通过重载,您可以定义多个“具有相同名称”但在同一对象或类上具有不同参数的方法。

答案 19 :(得分:0)

多态性与语言通过使用单个接口统一处理不同对象的能力有关;因此它与覆盖有关,所以接口(或基类)是多态的,实现者是覆盖的对象(同一个勋章的两个面)

无论如何,使用其他语言(例如c ++)可以更好地解释这两个术语之间的差异:如果基本函数是虚拟的,则c ++中的多态对象表现为java对应物,但如果该方法不是虚拟的,则代码跳转是解析静态,并且在运行时没有检查真实类型,因此,多态性包括对象根据用于访问它的接口而表现不同的能力;让我举一个伪代码的例子:

class animal {
    public void makeRumor(){
        print("thump");
    }
}
class dog extends animal {
    public void makeRumor(){
        print("woff");
    }
}

animal a = new dog();
dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

(假设makeRumor不是虚拟的)

java并不真正提供这种级别的多态性(也称为对象切片)。

动物a =新狗();     狗b =新狗();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

在这两种情况下它只会打印woff .. 因为a和b指的是类狗

答案 20 :(得分:0)

import java.io.IOException;

class Super {

    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName() + " - I'm parent");
        return null;
    }

}

class SubOne extends Super {

    @Override
    protected Super getClassName(Super s)  {
        System.out.println(this.getClass().getSimpleName() + " - I'm Perfect Overriding");
        return null;
    }

}

class SubTwo extends Super {

    @Override
    protected Super getClassName(Super s) throws NullPointerException {
        System.out.println(this.getClass().getSimpleName() + " - I'm Overriding and Throwing Runtime Exception");
        return null;
    }

}

class SubThree extends Super {

    @Override
    protected SubThree getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Returning SubClass Type");
        return null;
    }

}

class SubFour extends Super {

    @Override
    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Throwing Narrower Exception ");
        return null;
    }

}

class SubFive extends Super {

    @Override
    public Super getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and have broader Access ");
        return null;
    }

}

class SubSix extends Super {

    public Super getClassName(Super s, String ol) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading ");
        return null;
    }

}

class SubSeven extends Super {

    public Super getClassName(SubSeven s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading because Method signature (Argument) changed.");
        return null;
    }

}

public class Test{

    public static void main(String[] args) throws Exception {

        System.out.println("Overriding\n");

        Super s1 = new SubOne(); s1.getClassName(null);

        Super s2 = new SubTwo(); s2.getClassName(null);

        Super s3 = new SubThree(); s3.getClassName(null);

        Super s4 = new SubFour(); s4.getClassName(null);

        Super s5 = new SubFive(); s5.getClassName(null);

        System.out.println("Overloading\n");

        SubSix s6 = new SubSix(); s6.getClassName(null, null);

        s6 = new SubSix(); s6.getClassName(null);

        SubSeven s7 = new SubSeven(); s7.getClassName(s7);

        s7 = new SubSeven(); s7.getClassName(new Super());

    }
}