3

サブクラスからオーバーライドされたバージョンではなく、常に「ローカルに定義された」バージョンを実行するような方法で、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()すると、でbar()定義されたメソッドが呼び出され、オーバーライドされAて呼び出されて「Foo from B」が出力されます。foo()B

ではなくで定義されているメソッドをメソッドに強制bar()的に呼び出す方法はありますか? で定義されているメソッドを呼び出すために inを使用できるのと同じように? 残念ながら、使用してもサブクラスのバージョンが呼び出されます。またはのようなものでも機能しません。foo()ABsuper.foo()Bfoo()Athis.foo()((A) this).foo()A.this.foo()

foo()明らかに、 inのプライベート バージョンまたは最終バージョンを定義してA、代わりにそれを呼び出すことができます。しかし、解決策を望んでいます。上記のコード サンプルの「重要な行」を、foo() を呼び出す別の方法に変更して、できればリフレクションのようなトリックを使用せずに、「Foo from A」を出力させるだけです。

4

8 に答える 8

1

foo()呼び出される A に「内部」を含めることができます。

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」を出力します。

于 2012-11-15T18:02:14.167 に答える
1

あなたのオブジェクト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");
    }
}

GrannySmithApplesは常に緑色です (腐っていない限り、それはバナナの別の缶です)! を取得すると、通常の( 、など)と同じことがすべてできるという意味を除いてGrannySmithApple、それはもう ではありません。そして、通常の変換から変更されていないものは、明らかに同じです。AppleAppleprintColoreatAppleGrannySmithApple

于 2012-11-15T17:45:51.710 に答える
0

foo()new ...ステートメントで使用されるクラスのインスタンス メソッドを常に呼び出します。

要するに、あなたの質問に対する答えはNOだと思います。それはできません。動作の一部を完全にオーバーライドすることができなくなります。

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() {
...
}

}
于 2012-11-15T17:36:42.840 に答える
0

私の知る限り、Bオブジェクトは常に独自のfoo()メソッドを呼び出します。そうは言っても、スーパークラスのメソッドB.foo()を呼び出すように定義できます。foo()たとえば、B次のように定義できます。

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

そうすることで、 からのB呼び出しがあります。しかし、そうすると、常にそうなります。fooA

于 2012-11-15T17:39:09.287 に答える
0

この経験則があります:

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

-したがって、 B のインスタンスで呼び出された場合、常にそのfoo()メソッドが呼び出されます。Class B

-それでも、上記のコードを使用してのfoo()メソッドを呼び出す場合は、キーワードが必要です。Class Asuper

例えば:

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

       super.foo();
    }
}
于 2012-11-15T17:43:44.130 に答える
0

メソッドを静的にするか (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

}
于 2012-11-15T17:55:22.063 に答える
0

this「このクラス」ではなく「このオブジェクト」を参照します。

つまりB、拡張するオブジェクトがある場合、それが に言及してAいるスーパークラスでメソッドを実行すると、実際には のインスタンスを指すため、 でメソッドが実行されます。AthisBB

Aのメソッドは、デフォルトのメソッドと考えることができます。メソッドが実際のオブジェクトBでオーバーライドされている場合、代わりに常に呼び出されます。

設計を変更し、継承の代わりに構成を使用することをお勧めします。これにより、懸念事項が明確に分離され、コードが理解しやすくテストしやすくなります。

于 2012-11-15T17:47:05.980 に答える
0

他の人が述べているように、それを行う直接的な方法はありませんが、この構成の変形を検討することができます:

  void bar() {
    ClassA self = new ClassA();
    self.foo();  // <-- This is the important line!
  }
于 2012-11-15T17:51:59.587 に答える