繁体   English   中英

Java:在“this”类中调用函数而不是子类(类似于“super”)

[英]Java: Calling function in “this” class rather than a subclass (analog to “super”)

在Java中是否有可能以这样的方式调用可覆盖的方法:它总是执行“本地定义的”版本而不是从子类中重写的版本? 也就是说有一个模拟super引用这个类,而不是超类?

让我举一个代码示例,希望能说清楚我正在尝试做什么:

class A {
    void foo() {
        System.out.println("Foo from A");
    }

    void bar() {
        foo();  // <-- This is the important line!
    }
}

class B extends A {
    @Override
    void foo() {
        System.out.println("Foo from B");
    }
}

如果我执行new B().bar() ,它将调用A定义的bar()方法,该方法将调用foo()视为在B重写以打印“Foo from B”。

有没有办法可以强制bar()方法调用A定义的foo()方法而不是B 就像我可以在B使用super.foo()来调用A定义的foo()方法一样? 不幸的是,使用this.foo()仍然会调用子类的版本。 甚至像((A) this).foo()A.this.foo()这样的东西也行不通。

显然,我可以简单地在A定义foo()的私有版本或最终版本,然后调用它。 但是我希望有一个解决方案,我所做的就是将上面代码示例中的“重要线”更改为调用foo()的不同方式,让它打印“Foo from A”,最好不要像反射这样的技巧。

你的对象 B 不是 A 这是一个例子:

public class Apple {
    public void printColor() {
        System.out.println("I am red");
    }

    public void bar() {
       printColor();
    }
}

然后是子类:

public class GrannySmithApple extends Apple {
    public void printColor() {
        System.out.println("I am green");
    }
}

GrannySmithApple 是绿色的 ,总是(除非它们腐烂,但那是另外GrannySmithApple香蕉)! 一旦你有了一个GrannySmithApple ,它就不再Apple了,除非你可以用普通的AppleprintColoreat等)做一切相同的事情。有意义吗? 从常规AppleGrannySmithApple的转换之间没有任何变化,显然仍然是相同的。

你可以在A中调用一个“内部” foo()

class A {
    private void fooInternal() {
        System.out.println("Foo from A");
    }

    void foo() {
        fooInternal();
    }

    void bar() {
        fooInternal();
    }
}

class B extends A {
    @Override
    void foo() {
        System.out.println("Foo from B");
    }
}

new B().bar()现在将打印“Foo from A”,而new B().foo()将打印“Foo from B”。

foo()总是调用new ...语句中使用的类的实例方法。

总之,我认为你的问题的答案是否定的 ,不能做到。 它会阻止您完全覆盖部分行为。

class A {

method1() {
...
method2();
...
}

class B extends A {

// You can override method2 here to change the behaviour of method1 
// because it will call **your** version of method2
// You **don't** have to override method1 to achieve that

method2() {
...
}

}

据我所知, B对象总是调用自己的foo()方法。 话虽如此,可以定义B.foo()来调用超类' foo()方法。 例如,您可以按如下方式定义B

class B extends A {
    @Override public void foo() {
        super.foo();
    }
}

而这样做将有B调用fooA 但这样做会让它始终如此。

有这个经验法则:

In Inheritance the most specific version of the method for that class is called.

-因此,如果在B实例上调用它,将始终调用Class Bfoo()方法。

-仍然如果你想使用上面提到的代码调用Class Afoo()方法,那么你将需要super关键字。

例如:

class B extends A {
    @Override
    void foo() {

       super.foo();
    }
}

this引用了“这个对象”,而不是“这个类”。

这意味着,如果你有一个对象B扩展A ,当它执行超的方法A是提到this ,它实际上指向的实例B ,因此将执行的方法B

您可以将A中的方法视为默认方法 如果在实际对象B重写该方法,则将始终调用它。

我建议你改变你的设计并使用组合而不是继承 :这将确保明确分离关注点,并使你的代码更容易理解和测试。

正如其他人所说,没有直接的方法可以做到这一点,但你可能会考虑这个结构的变体:

  void bar() {
    ClassA self = new ClassA();
    self.foo();  // <-- This is the important line!
  }

要么使你的方法静态(baadddddd),要么改变你的设计。

实际上,为子类提供默认行为是没有意义的,它被定义为适应相关方法。

由于您的foo()方法似乎有所不同,您可以实现这样的策略模式:

interface BarProcess{
    void foo();
}

public class DefaultBarProcess implements BarProcess{
    void foo() {
       System.out.println("Foo from A");
    }
}

public class AnotherBarProcess implements BarProcess{
    void foo() {
       System.out.println("Foo from B");
    }
}

class A {

    private BarProcess barProcess;

    public A(Bar barProcess){
      this.barProcess = barProcess;
    }

    void bar() {
        barProcess.foo();
    }
}

class B extends A {  //deprecated! No need to exist

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM