426 Stimmen

Warum ist super.super.method(); in Java nicht erlaubt?

Ich lese diese Frage und dachte, das wäre leicht zu lösen (nicht, dass es nicht auch ohne zu lösen wäre), wenn man schreiben könnte:

@Override
public String toString() {
    return super.super.toString();
}

Ich bin mir nicht sicher, ob dies in vielen Fällen nützlich ist, aber ich frage mich なぜ es nicht ist und ob es so etwas in anderen Sprachen gibt.

Was haltet ihr davon?

EDITAR: Um das klarzustellen: Ja, ich weiß, das ist in Java unmöglich und ich vermisse es nicht wirklich. Ich habe nicht erwartet, dass das funktioniert und war überrascht, dass ich einen Compilerfehler bekomme. Ich hatte nur die Idee und möchte sie gerne diskutieren.

0voto

Yakov Fain Punkte 11164

IMO ist dies ein sauberer Weg, um die super.super.sayYourName() Verhalten in Java.

public class GrandMa {  
    public void sayYourName(){  
        System.out.println("Grandma Fedora");  
    }  
}  

public class Mama extends GrandMa {  
    public void sayYourName(boolean lie){  
        if(lie){   
            super.sayYourName();  
        }else {  
            System.out.println("Mama Stephanida");  
        }  
    }  
}  

public class Daughter extends Mama {  
    public void sayYourName(boolean lie){  
        if(lie){   
            super.sayYourName(lie);  
        }else {  
            System.out.println("Little girl Masha");  
        }  
    }  
}  

public class TestDaughter {
    public static void main(String[] args){
        Daughter d = new Daughter();

        System.out.print("Request to lie: d.sayYourName(true) returns ");
        d.sayYourName(true);
        System.out.print("Request not to lie: d.sayYourName(false) returns ");
        d.sayYourName(false);
    }
}

Ausgabe:

Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha

0voto

DayaMoon Punkte 337

Meiner Meinung nach ist dies ein Problem, das gegen das Erbschaftsabkommen verstößt.
Indem Sie eine Klasse erweitern, befolgen/vereinbaren Sie ihr Verhalten, ihre Eigenschaften
Während beim Aufruf super.super.method() Sie wollen Ihre eigene Gehorsamsvereinbarung brechen.

Man kann nicht einfach die Rosinen aus der Superklasse herauspicken .

Es kann jedoch Situationen geben, in denen Sie das Bedürfnis haben, Folgendes anzurufen super.super.method() - in der Regel ein schlechtes Design-Zeichen, in Ihrem Code oder in dem Code, den Sie erben!
Wenn die super y super super Klassen nicht umgestaltet werden können (z. B. Legacy-Code), dann sollten Sie sich für Komposition statt Vererbung entscheiden.

Kapselungsbruch ist, wenn Sie @Override einige Methoden durch Aufbrechen des gekapselten Codes. Die Methoden, die nicht überschrieben werden sollen, sind mit endgültig .

0voto

user2490562 Punkte 11

Es ist einfach zu machen. Zum Beispiel:

C Unterklasse von B und B Unterklasse von A. Beide haben zum Beispiel die Methode 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");
    }

}

Klasse C ausführen Die Ausgabe wird sein: Klasse A Klasse C

Anstelle der Ausgabe: Klasse A Klasse B Klasse C

0voto

D.Motyl Punkte 1

In C# können Sie eine Methode eines beliebigen Vorgängers wie folgt aufrufen:

public class A
    internal virtual void foo()
...
public class B : A
    public new void foo()
...
public class C : B
    public new void foo() {
       (this as A).foo();
    }

Sie können dies auch in Delphi tun:

type
   A=class
      procedure foo;
      ...
   B=class(A)
     procedure foo; override;
     ...
   C=class(B)
     procedure foo; override;
     ...
A(objC).foo();

Aber in Java kann man einen solchen Fokus nur mit einem bestimmten Gerät erreichen. Ein möglicher Weg ist:

class A {               
   int y=10;            

   void foo(Class X) throws Exception {  
      if(X!=A.class)
         throw new Exception("Incorrect parameter of "+this.getClass().getName()+".foo("+X.getName()+")");
      y++;
      System.out.printf("A.foo(%s): y=%d\n",X.getName(),y);
   }
   void foo() throws Exception { 
      System.out.printf("A.foo()\n");
      this.foo(this.getClass()); 
   }
}

class B extends A {     
   int y=20;            

   @Override
   void foo(Class X) throws Exception { 
      if(X==B.class) { 
         y++; 
         System.out.printf("B.foo(%s): y=%d\n",X.getName(),y);
      } else { 
         System.out.printf("B.foo(%s) calls B.super.foo(%s)\n",X.getName(),X.getName());
         super.foo(X);
      } 
   }
}

class C extends B {     
   int y=30;            

   @Override
   void foo(Class X) throws Exception { 
      if(X==C.class) { 
         y++; 
         System.out.printf("C.foo(%s): y=%d\n",X.getName(),y);
      } else { 
         System.out.printf("C.foo(%s) calls C.super.foo(%s)\n",X.getName(),X.getName());
         super.foo(X);
      } 
   }

   void DoIt() {
      try {
         System.out.printf("DoIt: foo():\n");
         foo();         
         Show();

         System.out.printf("DoIt: foo(B):\n");
         foo(B.class);  
         Show();

         System.out.printf("DoIt: foo(A):\n");
         foo(A.class);  
         Show();
      } catch(Exception e) {
         //...
      }
   }

   void Show() {
      System.out.printf("Show: A.y=%d, B.y=%d, C.y=%d\n\n", ((A)this).y, ((B)this).y, ((C)this).y);
   }
} 

objC.DoIt() Ergebnisausgabe:

DoIt: foo():
A.foo()
C.foo(C): y=31
Show: A.y=10, B.y=20, C.y=31

DoIt: foo(B):
C.foo(B) calls C.super.foo(B)
B.foo(B): y=21
Show: A.y=10, B.y=21, C.y=31

DoIt: foo(A):
C.foo(A) calls C.super.foo(A)
B.foo(A) calls B.super.foo(A)
A.foo(A): y=11
Show: A.y=11, B.y=21, C.y=31

-1voto

Ashtheking Punkte 19

Wenn Sie davon ausgehen, dass Sie die Oberklasse benötigen werden, können Sie in einer Variablen für diese Klasse darauf verweisen. Zum Beispiel:

public class Foo
{
  public int getNumber()
  {
    return 0;
  }
}

public class SuperFoo extends Foo
{
  public static Foo superClass = new Foo();
  public int getNumber()
  {
    return 1;
  }
}

public class UltraFoo extends Foo
{
  public static void main(String[] args)
  {
    System.out.println(new UltraFoo.getNumber());
    System.out.println(new SuperFoo().getNumber());
    System.out.println(new SuperFoo().superClass.getNumber());
  }
  public int getNumber()
  {
    return 2;
  }
}

Sollte ausgedruckt werden:

2
1
0

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X