多态性与重写与重载

Bri*_*n G 340 java oop polymorphism overriding overloading

就Java而言,当有人问:

什么是多态?

超载重载是一个可以接受的答案?

我认为还有更多的东西.

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

我认为超载肯定不是正确的答案.

Chr*_*ore 881

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

public abstract class Human{
   ...
   public abstract void goPee();
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

现在我们可以告诉整个房间充满了人类去撒尿.

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();
}
Run Code Online (Sandbox Code Playgroud)

运行这将产生:

Stand Up
Sit Down
...
Run Code Online (Sandbox Code Playgroud)

  • 这个例子也很好地突出了使用分层系统来描述生物系统的难度.有些人,比如非常年轻,几乎在任何位置撒尿 - 而婴儿也不容易被告知goPee().有些人是双性人,其中"男性"或"女性"的生物标签变得相当不明确; 社会意义更加复杂.作为教学示例,它显示了建模假设如何产生负面结果,例如暗示失禁或双性人的某人(例如,OO编程的学生)实际上并不是人类. (99认同)
  • @yuudachi.我在教课时想出了这个例子.规范的"银行账户"类并没有真正表达基类的"抽象性".另一个典型的例子(动物,制造噪音)太抽象了,无法理解.我正在寻找一个具有太明显的子类的单一基础.实际上,goPee()是我想出的唯一一个不是性别歧视或刻板印象的例子.(虽然在课堂上,我打印在"左边的大厅"而不是站起来或坐下.) (37认同)
  • @AndrewDalke,+1关于生物复杂性的注释.此外,`goPee`不会将引力场作为输入.这种对全局状态的依赖使单元测试"CatheterizedIntersexAstronaut"变得困难,并表明子类化可能并不总是特征组合的最佳方法. (19认同)
  • 我能想到至少有少数人会反驳你的"你不能创造一个既不是男性也不能创造男性"的论点,尽管它仍然适用于你的代码...糟糕的抽象我想我说的是?;) (7认同)
  • 我认为重要的是要指出它只是多态性,因为调用 goPee() 的哪个版本只能在运行时确定。虽然这个例子暗示了这一点,但很好地指出为什么这就是多态性。此外,它不需要兄弟类。也可以是亲子关系。甚至完全不相关的类恰好具有相同的功能。一个例子是 .toString() 函数。可以在任何对象上随机调用它,但编译器永远无法确切知道是哪种类型的对象。 (2认同)
  • @AndrewDalke,如果用 Cat 和 Dog 类(它们是 Animal 抽象类的子类)来解释 OOP 原理会怎样?这是否意味着老鼠因此就不是动物? (2认同)

The*_*beg 94

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

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

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

  • 不正确."Ad hoc多态性"是你在**重载**部分中描述的,*是*多态的情况. (8认同)
  • 这是旧的,但是Polymorphism并不意味着另一个类必须在继承树中.如果您认为接口是继承树的一部分,那么它在Java中完成,而在Go中则不是,其中接口是隐式实现的. (7认同)
  • 实际上,根本不需要多态类. (5认同)
  • “它与覆盖或多态性无关”。这个说法是错误的。 (4认同)
  • 我是新手,如果我错了,请纠正我,但我不会说重载与多态无关.至少在Java中,多态性是在根据调用者的类型选择实现时,而重载是在根据参数的类型选择实现时,不是吗?看到两者之间的相似性有助于我理解它. (3认同)

Mar*_*osi 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 ());
}
Run Code Online (Sandbox Code Playgroud)

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

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


小智 43

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

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

  1. 方法覆盖
  2. 方法重载

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

方法重写意味着我们在不同的类中使用方法名称,这意味着在子类中使用父类方法.

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

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

  • +1回答很好.接受的答案只解释了一种多态性.这个答案是完整的. (4认同)
  • 多态是一种范式(OOP),但覆盖和重载是语言设施。 (3认同)

Pat*_*ney 39

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

您可以在一个或多个子类中重写的类中拥有一个方法.该方法根据用于实例化对象的类来执行不同的操作.

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

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

    class Wine extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature < 10;
       }
    }
Run Code Online (Sandbox Code Playgroud)

您还可以使用两个或多个参数集重载的方法 .该方法根据传递的参数类型执行不同的操作.

    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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 正如我在此回答的那样,我不同意 - 这两个特征不是正交的,而是密切相关的.多态性!=继承.你有我的投票权. (7认同)
  • 换句话说,键入多态与ad-hoc多态.我正在推荐这个答案,即使它没有尽可能完整,因为它正确地指出重载和覆盖都与多态性有关.说OOP语言中的多态只能通过类继承实现是完全错误的 - 我们应该记住除了Java和C++之外还有一些其他的OOP语言,其中可以使用多重调度,ad hoc多态,参数多态等概念. . (2认同)
  • @rsenna这可能是不完整的,但它比其他恕我直言更好地回答了这个问题.另外,非常好的是你提到了ad-hoc和参数多态. (2认同)

Ale*_*x B 14

你是正确的,重载不是答案.

两者都不是最重要的.覆盖是获得多态性的手段.多态性是对象根据其类型改变行为的能力.当展示多态性的对象的调用者不知道对象是什么特定类型时,这是最好的证明.

  • 它不应该是对象的行为改变,而是他的实现.相同的行为,不同的实现,这是多态性. (3认同)

Pet*_*yer 11

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

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

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

  • 要明确的是,我认为应该说明不同的形式 - 我甚至没有充分地做过 - 因为这里有一些答案是绝对的.我恭敬地不同意在"程序员上下文......'多态性'总是意味着'基于继承的多态'' (4认同)
  • 我认为重载最好归类为Ad-hoc_polymorphism http://en.wikipedia.org/wiki/Parametric_polymorphism#Ad-hoc_polymorphism_with_early_binding (2认同)

小智 7

多态只是意味着"多种形式".

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

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

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

  • 绝对是最好的答案。多态可以应用于所有语言结构,无论是名词(类)还是动词(方法)。 (2认同)

mxg*_*mxg 6

多态性是一个对象以多种形式出现的能力。这涉及到使用继承和虚函数来构建一系列可以互换的对象。基类包含虚拟函数的原型,可能未实现或具有应用程序指定的默认实现,并且各个派生类各自以不同的方式实现它们以影响不同的行为。


Bri*_*n G 6

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

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

这就是我认为的多态性.


Mat*_*att 5

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

重写是通过子类中具有相同名称的函数来更改基类的行为。

所以多态性与重写有关,但与真正的重载无关。

然而,如果有人对“什么是多态性?”这个问题给了我一个简单的“重写”答案。我想要求进一步的解释。


Dev*_*per 5

虽然在这篇文章中已经详细解释了多态性,但我想更加强调为什么是它的一部分。

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

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

假设您是一家电视公司的软件工程师,您需要为 Volume、Brightness 和 Color 控制器编写软件,以根据用户命令增加和减少它们的值。

您首先通过添加为这些功能中的每一个编写类

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

应用程序版本 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;
        }

    }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

TV 应用程序版本 1 中的问题

  1. Adjust(int value) 代码在所有三个类中都是重复的。您希望尽量减少代码重复。(但是你没有想到通用代码,把它移到某个超类中以避免重复代码)

只要您的应用程序按预期工作,您就决定接受它。

有时,您的老板会回来找您并要求您向现有应用程序添加重置功能。重置会将所有 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;
            }

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,您的应用程序已准备好具有重置功能。但是,现在你开始意识到

TV 应用程序版本 2 中的问题

  1. 如果产品中引入了新控制器,则必须更改重置功能代码。
  2. 如果控制器的数量增长得非常高,您将无法保存控制器的引用。
  3. 重置功能代码与所有控制器类的代码紧密耦合(获取和设置默认值)。
  4. 重置要素类 (ResetFunctionV2) 可以访问 Controller 类的 (adjust) 的其他方法,这是不可取的。

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

现在您开始认为要添加的这个新功能类似于重置功能,如果您不重构您的应用程序,应用程序问题 (V2) 将成倍增加。

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

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

通过这些改进,您的电视应用程序版本 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;
            }

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

尽管 V2 的问题列表中列出的大部分问题都得到了解决,除了

TV 应用程序版本 3 中的问题

  1. 重置要素类 (ResetFunctionV3) 可以访问 Controller 类的 (adjust) 的其他方法,这是不可取的。

同样,您考虑解决这个问题,因为现在您还有另一个功能(启动时更新驱动程序)要实现。如果您不修复它,它也会被复制到新功能中。

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

  1. 重置功能。
  2. 驱动程序更新。

并让您的第一个具体类实现它们,如下所示

应用程序版本 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;