超类方法需要引用其另一个(虽然被重写)方法

时间:2015-04-10 18:36:39

标签: java oop inheritance override method-overriding

拥有以下超类:

public class SuperClass {

    protected Integer a;
    protected Integer b;

    public void doSomething() {
        this.a = 10;
    }

    public void doEverything() {
        SuperClass.this.doSomething();
        this.b = 20;
    }

    public static void main(String[] args) {
        SuperClass instance = new SubClass();
        instance.doEverything();
        System.out.println(instance.a); //should print 10
        System.out.println(instance.b);
    }
}

以下子类:

public class SubClass extends SuperClass {

    @Override
    public void doSomething() {
        super.doSomething();
        super.a *= 10;
    }

    public void doEverything() {
        super.doEverything();
        this.b += 5;
    }
}

输出:

  

100

     

25

因此,SuperClass.this.doSomething();正在访问SubClass的{​​{1}},但我需要它来访问doSomething的{​​{1}}。在这种情况下,我没有SuperClass关键字,因为我已经超级了!

  1. 有没有办法引用¹ doSomething,所以它会为第一个输出super输出值?

    ¹我对引用感兴趣:我们当然可以将SuperClass.this.doSomething的{​​{1}}提取到辅助私有方法并直接访问它

  2. 如果没有办法,超类方法需要访问另一个(虽然被覆盖)方法的情况是否意味着我的OOP设计不正确?为什么?

4 个答案:

答案 0 :(得分:3)

我假设您从C ++背景来到Java。语言在概念和语法上类似,但它们在实现中是不同的。

你可以用Java实现我的想法,但结构与C ++的结构不同。

在Java中,示例中的构造SuperClass.thisthis完全相同,因此SuperClass.this.doSomething();恰好就是doSomething()。那么为什么Java根本就有构造SuperClass.this?它的含义与继承无关。它在嵌套类的上下文中很有用。

想象一下这样的结构:

class A {
    class B {
        public void doSomething() {
         // this here refers to an instance of the class B
         System.out.println(this);
         // We need to write is this way,
         // because this hides the this reference to the instance of A.
         // A.this is the instance of A where this is nested
         System.out.println(A.this); 
     }
}

那么如何确保能够在类中具有子类可以覆盖的方法,并且仍然能够调用特定的实现?

嗯,从严格意义上说,你不能。你可以做的是创建一个final方法,它不能被覆盖,并从非最终方法调用它。

class SuperClass {
    public void doSomething() {
        doSuperClassyThing();
    }

    public final void doSuperClassyThing() { // cannot be overridden
        ...
    }
}

您可以在Template Method Pattern中看到类似的方法(目标略有不同)。

答案 1 :(得分:2)

答案是你无法引用它。执行此操作的唯一方法是您已经了解的私有帮助方法。

如果你想知道原因,我想这只是因为它会无缘无故地使语言复杂化;通过使用私有帮助器方法,您始终可以获得相同的结果。语法SuperClass.this.doSomething()已被用于其他内容。这意味着如果doSomething是一个封闭类,则在封闭实例上调用方法SuperClass

答案 2 :(得分:2)

你无法做你想做的事。多态性的工作方式是做你所看到的。

这意味着没有直接的方法从SuperClass.doSomething()调用SuperClass.doSomething()而不通过SubClass.doSomething(),除非您正在使用SuperClass的实际实例。

在其他一些语言中,您有权告诉如何处理此问题,例如在c ++中使用关键字virtual,但在java中,您没有这个选项。所有方法都被动态绑定,因此您无法做到这一点。你根本不能覆盖或阻止它被覆盖。

答案 3 :(得分:1)

如果您发现自己处于这种情况,也许您应该重新考虑并认为类结构 尚未正确。

尝试实施以下方法之一:

  1. 继承的构成。
  2. 创建一个新的继承级别(中间有一个引用super的类)。
  3. 与(2.)相同,但使用内部类。
  4. 将所需方法解压缩到单独的私有方法,并在适用的地方调用它。
  5. 由于(1.)不会像其他人一样干,(4。)留下一种解决方法的感觉,并且(2.)需要创建一个新文件并在{{1}之外引用};我认为最接近的方法是(3.),这是在SuperClass内以某种方式引用super的唯一解决方案(虽然它实际上是在SuperClass内部类上引用的):< / p>

    <强> SuperClass.java:

    SuperClass

    <强> SubClass.java:

    public abstract class SuperClass {
    
        protected Integer a;
        protected Integer b;
    
        public void doSomething() {
            this.a = 10;
        }
    
        public abstract void doEverything();
    
        public static class Impl extends SuperClass {
    
            @Override
            public void doEverything() {
                super.doSomething();
                this.b = 20;
            }
        }
    
        public static void main(String[] args) {
            SuperClass instance = new SubClass();
            instance.doEverything();
            System.out.println(instance.a); //prints 10
            System.out.println(instance.b);
        }
    }