【问题标题】:How to call over-ridden abstract class methods如何调用重写的抽象类方法
【发布时间】:2011-12-26 04:35:01
【问题描述】:

我有这样的场景

这是抽象类

    abstract class A
    {
            public void add()
            {
                    //do something
            }
    }

这是在抽象类之上扩展的类

    class B extends A
    {
            @Override
            public void add()
            {
                    //do something else
            }
    }

这是我要调用两个添加方法的类

    class C
    {
            A a = new B();

            // Calls B's add method

            a.add();

            // Call A's add method ???
    }

如何调用A的add方法???

【问题讨论】:

  • 看到这个link
  • 在 Class B 的 add() 中调用 super.add()

标签: java inheritance abstract-class abstract


【解决方案1】:

我得到了我想要的,但这里的方式不同---

    class D extends A
    {
            public add()
            {
                    //Log here..........
                    super.add();
            }
    }

这将帮助我不要通过避免 super.add(); 来强制 B 调用 A 的默认实现;

因为我们已经覆盖它以更改功能。

    class C
    {
            A a = new B();
            // Call B's Add method
            a.add();

            a = new D();
            // Call A's Add method via D
            a.add();
    }

我认为没有比这更好的方法了:)

【讨论】:

    【解决方案2】:
    class B extends A
    {
    //over ride method
    public add()
    {
        //do something else
    }
    
    public add2()
    {
        super.add();
    }
    }
    
    
    class C {
    A a = new B();
    
    // Calls B's add method
    a.add();
    
    // Call A's add method
    a.add2();
    }
    

    【讨论】:

      【解决方案3】:

      正如上面各种人所解释的那样,你不能。如果我们尝试了解您想要实现的目标,我猜您需要的是一个接口和两个类。

      interface AddInterface {
       public void add();
      }
      
      class A implements AddInterface {
      //your abstract class' version of add goes here
      }
      
      class B implements AddInterface {
      //your other add definition.
      }
      

      您最终会用 AddInterface 替换对 A 的引用。 同样,这完全取决于您想要实现的目标。

      【讨论】:

        【解决方案4】:

        你不能。这就是多态性和封装的全部意义——您已经创建了B 的实例,因此B 可以决定add 的含义。例如,也许B 正在尝试执行一些关于何时可以调用add 的业务规则——如果你可以绕过这些规则并直接在B 的实例上调用A.add(),那将毫无用处。 B.add() 的实现可以决定何时以及是否调用super.add(),但代码外部 B 无法做出该决定。

        【讨论】:

        • "You can't" 是非常失败主义的——C++ 也有多态性,但是如果你喜欢调用基类的实现,你可以很高兴地说b.A::add()(即使A::add() 是纯的-virtual)... :-) 我想更合适的措辞是“Java 由设计决定,为了您的舒适,不会让您面临任何不必要的选择。”
        • @KerrekSB:我不认为这是失败主义,而是不会像 C++ 那样被破坏。做不到是好事,所以比失败主义更乐观。
        • @KerrekSB:这不是“不必要的选择”的问题——而是打破多态性的问题。你不同意“你不能”的准确性吗?仅仅因为你可以用另一种语言做一些危险的事情并不意味着你可以或应该能够这样做用另一种语言。
        • @JonSkeet:嗯,这是一个意见和设计问题......我也可以争辩说,用户可能完全意识到她有一个派生对象并且希望能够使用那个额外的信息。我不相信这会“破坏”任何东西——毕竟,最简单的语法总是能让你得到“预期的”行为,并且任何其他行为都会在语法中立即可见。所以...是的,调用基础实现是 Java 决定不向派生类的用户提供的选择。
        • @KerrekSB:它破坏了类推理其内部状态并保持其一致性的能力。这对我来说是一个很大的破坏。
        【解决方案5】:

        您正在寻找super

        class B extends A
        {
                //over ride method
                public add()
                {
                        super.add();
                        //do something else
                }
        }
        

        【讨论】:

        • 但是 super 只能在this-Context 中工作(所以你不能使用a.super.add() 来调用A.add()
        • @PhilippWendt:哦,绝对 - 因此我将它包含在 B 中的示例 add()
        【解决方案6】:

        你不能,因为它会破坏多态性。如果 B 覆盖 A 的 add 方法,那是因为它必须以另一种方式添加来满足其合同。不按照需要的方式进行操作会破坏 B 的不变量,并且可能还会破坏 A 的不变量。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-30
          • 1970-01-01
          • 1970-01-01
          • 2016-06-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多