A、B、Cの3つのクラスがあるとします。
すべてにpublic void foo()
メソッドが定義されています。
ここで、Cのfoo()
メソッドから、Aのfoo()
メソッドを呼び出します(その親Bのメソッドではなく、スーパースーパークラスAのメソッド)。
super.super.foo();
を試しましたが、構文が無効です。どうすればこれを達成できますか?
リフレクションは使用できません。何かのようなもの
_Class superSuperClass = this.getClass().getSuperclass().getSuperclass();
superSuperClass.getMethod("foo").invoke(this);
_
superSuperClassでfoo-Methodを呼び出しても、invokeで「this」を指定すると、C.foo()
が引き続き使用されるため、InvocationTargetException
になります。これは、すべてのJavaメソッドが仮想メソッドであるという事実からの結果です。
Bクラスからの助けが必要なようです(superFoo(){ super.foo(); }
メソッドを定義するなど)。
とはいえ、このようなことを試してみると、設計上の問題のように見えるので、背景を教えておくと役立ちます。なぜこれを行う必要があるのですか?
できません-カプセル化が壊れるからです。
ownクラスのカプセル化が壊れていることがわかっていると想定されているため、スーパークラスのメソッドを呼び出すことができ、それを回避します...しかし、スーパークラスが適用しているルールがわからないため、そこで実装をバイパスすることはできません。
簡単な方法ではできません。
これはあなたができると思うことです:
クラスBにブール値を設定します。次に、Cから[super foo]
のようにBのfooを呼び出す必要がありますが、これを行う前にブール値をtrueに設定します。 Bのfooでboolがtrueかどうかを確認し、その中でステップを実行せず、Aのfooを呼び出すだけです。
お役に立てれば。
はい、できます。これはハックです。このようにプログラムを設計しないようにしてください。
class A
{
public void method()
{ /* Code specific to A */ }
}
class B extends A
{
@Override
public void method()
{
//compares if the calling object is of type C, if yes Push the call to the A's method.
if(this.getClass().getName().compareTo("C")==0)
{
super.method();
}
else{ /*Code specific to B*/ }
}
}
class C extends B
{
@Override
public void method()
{
/* I want to use the code specific to A without using B */
super.method();
}
}
以前の回答を引用するには、「できません-カプセル化が壊れるからです。」それに追加したいのは:
ただし、メソッドがstatic
(public
またはprotected
)の場合は、可能です。 静的メソッドを上書きする はできません。
public static
メソッドは、実際にこれを実行できることを証明するのは簡単です。
ただし、protected
の場合は、継承パス内のスーパークラスへのキャストを実行するために、メソッドの1つからそのスーパークラスメソッドが呼び出されます。
これは私が私の答えで探究しているコーナーケースです:
public class A {
static protected callMe(){
System.out.println("A");
}
}
public class B extends A {
static protected callMe(){
System.out.println("B");
}
}
public class C extends B {
static protected callMe(){
System.out.println("C");
C.callMe();
}
public void accessMyParents(){
A a = (A) this;
a.callMe(); //calling beyond super class
}
}
答えは「いいえ」のままですが、できる限りのケースを示したいだけですが、それはおそらく意味をなさず、単なる演習です。
リフレクションAPIを使用する前に、そのコストについて検討してください。
簡単です。例えば:
BのCサブクラスとAのBサブクラス。3つとも、たとえばmethodName()メソッドを持っています。
public abstract class A {
public void methodName() {
System.out.println("Class A");
}
}
public class B extends A {
public void methodName() {
super.methodName();
System.out.println("Class B");
}
// Will call the super methodName
public void hackSuper() {
super.methodName();
}
}
public class C extends B {
public static void main(String[] args) {
A a = new C();
a.methodName();
}
@Override
public void methodName() {
/*super.methodName();*/
hackSuper();
System.out.println("Class C");
}
}
実行クラスC出力は次のようになります:クラスAクラスC
出力の代わりに:クラスAクラスBクラスC
私の単純なケースでは、BとCの等しいメソッドをカプセル化する抽象クラスからBとCを継承する必要がありました。
_ A
|
Abstr
/ \
B C
_
それは問題を解決しませんが、CがBに類似している場合、単純なケースで使用できます。たとえば、Cが初期化されているが、Bの初期化子を使用したくない場合。その後、単純にAbstrメソッドを呼び出します。
これは、BとCの共通部分です。
_public abstract class Abstr extends AppCompatActivity {
public void showProgress() {
}
public void hideProgress() {
}
}
_
これはBであり、AppCompatActivity
に存在する独自のメソッドonCreate()
を持っています。
_public class B extends Abstr {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Call from AppCompatActivity.
setContentView(R.layout.activity_B); // B shows "activity_B" resource.
showProgress();
}
}
_
Cは独自のレイアウトを示しています。
_public class C extends Abstr {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Call from AppCompatActivity.
setContentView(R.layout.activity_C); // C shows "activity_C" resource.
showProgress();
}
}
_
私の同様の問題を解決した回避策があります:
クラスA、B、およびCのシナリオを使用すると、カプセル化を解除せず、クラスB内でクラスCを宣言する必要もないメソッドがあります。回避策は、クラスBのメソッドを別の保護されたメソッドに移動することです。
次に、それらのクラスBのメソッドが必要ない場合は、単にそのメソッドをオーバーライドしますが、そのメソッド内で「スーパー」を使用しないでください。オーバーライドして何もしないと、そのクラスBメソッドは効果的に無効になります。
public class A {
protected void callMe() {
System.out.println("callMe for A");
}
}
public class B extends A {
protected void callMe() {
super.callMe();
methodsForB(); // Class B methods moved out and into it's own method
}
protected void methodsForB() {
System.out.println("methods for B");
}
}
public class C extends B {
public static void main(String[] args) {
new C().callMe();
}
protected void callMe() {
super.callMe();
System.out.println("callMe for C");
}
protected void methodsForB() {
// Do nothing thereby neutralising class B methods
}
}
結果は次のようになります。
callMe for A
callMe for C
スーパークラスがオーバーライドされたトップクラスのメソッドを呼び出すという問題がありました。これは私の回避策でした...
//これはa1()がスーパークラスのメソッドを呼び出して失敗するため、トップクラスのメソッドを呼び出すことができません
class foo1{
public void a1(){
a2();
}
public void a2(){}
}
class foo2 extends foo1{
{
public void a1(){
//some other stuff
super.a1();
}
public void a2(){
//some other stuff
super.a2();
}
//これにより、適切なスーパークラスメソッドの呼び出しが保証されます//パブリックメソッドはプライベートメソッドのみを呼び出すため、スーパークラスの機能に影響を与えることなく、すべてのパブリックメソッドをオーバーライドできます。
class foo1{
public void a1(){
a3();}
public void a2(){
a3();}
private void a3(){
//super class routine
}
class foo2 extends foo1{
{
public void a1(){
//some other stuff
super.a1();
}
public void a2(){
//some other stuff
super.a2();
}
これがお役に立てば幸いです。 :)
それは不可能であり、スーパークラスの実装のみを呼び出すことに制限されています。
私 匂い ここで何か怪しい。
「できるはずだからといって」、限界を超えているのではないでしょうか。これがあなたが得ることができる最高のデザインパターンであると確信していますか?それをリファクタリングしてみましたか?