¿Por qué es super.superusuario.method (); ¿no está permitido en Java?


Leí esta pregunta y pensé que se resolvería fácilmente (no es que no se pueda resolver sin) si uno pudiera escribir:

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

No estoy seguro de si es útil en muchos casos, pero me pregunto por qué no lo es y si algo así existe en otros idiomas.

¿Qué piensan ustedes?

EDITAR: Para aclarar: sí lo sé, eso es imposible en Java y realmente no lo extraño. Esto no es nada que esperaba trabajar y me sorprendió conseguir un error del compilador. Acabo de tener la idea y me gusta discutirla.

Author: Community, 2009-02-25

21 answers

Viola la encapsulación. No deberías ser capaz de evitar el comportamiento de los padres. Tiene sentido a veces ser capaz de eludir el comportamiento de su propia clase (particularmente desde dentro del mismo método) pero no de su padre. Por ejemplo, supongamos que tenemos una base "colección de elementos", una subclase que representa "una colección de elementos rojos" y una subclase de la que representa "una colección de elementos rojos grandes". Tiene sentido tener:

public class Items
{
    public void add(Item item) { ... }
}

public class RedItems extends Items
{
    @Override
    public void add(Item item)
    {
        if (!item.isRed())
        {
            throw new NotRedItemException();
        }
        super.add(item);
    }
}

public class BigRedItems extends RedItems
{
    @Override
    public void add(Item item)
    {
        if (!item.isBig())
        {
            throw new NotBigItemException();
        }
        super.add(item);
    }
}

Eso está bien-RedItems puede siempre tenga la confianza de que los elementos que contiene son todos de color rojo. Ahora supongamos que somos capaces de llamar a super.superusuario.add ():

public class NaughtyItems extends RedItems
{
    @Override
    public void add(Item item)
    {
        // I don't care if it's red or not. Take that, RedItems!
        super.super.add(item);
    }
}

Ahora podemos añadir lo que queramos, y el invariante en RedItems se rompe.

¿Eso tiene sentido?

 437
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-31 14:45:02

Creo que Jon Skeet tiene la respuesta correcta. Me gustaría añadir que puede acceder a variables sombreadas de superclases de superclases lanzando this:

interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
        int x = 3;
        void test() {
                System.out.println("x=\t\t"          + x);
                System.out.println("super.x=\t\t"    + super.x);
                System.out.println("((T2)this).x=\t" + ((T2)this).x);
                System.out.println("((T1)this).x=\t" + ((T1)this).x);
                System.out.println("((I)this).x=\t"  + ((I)this).x);
        }
}

class Test {
        public static void main(String[] args) {
                new T3().test();
        }
}

Que produce la salida:

x=              3
super.x=        2
((T2)this).x=   2
((T1)this).x=   1
((I)this).x=    0

(ejemplo del JLS )

Sin embargo, esto no funciona para llamadas a métodos porque las llamadas a métodos se determinan en función del tipo de tiempo de ejecución del objeto.

 61
Author: Michael Myers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-26 19:49:54

Creo que el siguiente código permite usar super.superusuario...superusuario.method () en la mayoría de los casos. (incluso si es feo hacer eso)

En breve

  1. crear instancia temporal de tipo antepasado
  2. copiar valores de campos de original objeto a temporal
  3. invocar el método de destino en el objeto temporal
  4. copiar los valores modificados al objeto original

Uso:

public class A {
   public void doThat() { ... }
}

public class B extends A {
   public void doThat() { /* don't call super.doThat() */ }
}

public class C extends B {
   public void doThat() {
      Magic.exec(A.class, this, "doThat");
   }
}


public class Magic {
    public static <Type, ChieldType extends Type> void exec(Class<Type> oneSuperType, ChieldType instance,
            String methodOfParentToExec) {
        try {
            Type type = oneSuperType.newInstance();
            shareVars(oneSuperType, instance, type);
            oneSuperType.getMethod(methodOfParentToExec).invoke(type);
            shareVars(oneSuperType, type, instance);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private static <Type, SourceType extends Type, TargetType extends Type> void shareVars(Class<Type> clazz,
            SourceType source, TargetType target) throws IllegalArgumentException, IllegalAccessException {
        Class<?> loop = clazz;
        do {
            for (Field f : loop.getDeclaredFields()) {
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                }
                f.set(target, f.get(source));
            }
            loop = loop.getSuperclass();
        } while (loop != Object.class);
    }
}
 37
Author: Nico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-01 23:17:58

No tengo suficiente reputación para comentar, así que agregaré esto a las otras respuestas.

Jon Skeet responde excelentemente, con un hermoso ejemplo. Matt B tiene un punto: no todas las superclases tienen supers. Tu código se rompería si llamabas a un super de un super que no tenía super.

La programación orientada a objetos (que es Java) se trata de objetos, no de funciones. Si desea programación orientada a tareas, elija C++ o algo más. Si su objeto no cabe en él es super clase, luego, debe agregarlo a la" clase de abuelo", crear una nueva clase o encontrar otro super en el que encaje.

Personalmente, he encontrado que esta limitación es una de las mayores fortalezas de Java. El código es algo rígido en comparación con otros idiomas que he usado, pero siempre sé qué esperar. Esto ayuda con el objetivo" simple y familiar " de Java. En mi mente, llamando a super.super no es simple o familiar. Tal vez los desarrolladores sintieron lo mismo?

 10
Author: EllaJo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-07 14:28:39

Hay algunas buenas razones para hacer esto. Es posible que tenga una subclase que tiene un método que se implementa incorrectamente, pero el método padre se implementa correctamente. Debido a que pertenece a una biblioteca de terceros, es posible que no pueda/no quiera cambiar la fuente. En este caso, desea crear una subclase pero anular un método para llamar al super.super método.

Como muestran algunos otros carteles, es posible hacer esto a través de la reflexión, pero debería ser posible hacer algo así como

(SuperSuperClase esto).theMethod ();

Estoy lidiando con este problema en este momento - la solución rápida es copiar y pegar el método superclass en el método subsubclass:)

 8
Author: Larry Watanabe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-07 14:24:56

Además de los muy buenos puntos que otros han hecho, creo que hay otra razón: ¿qué pasa si la superclase no tiene una superclase?

Dado que cada clase se extiende naturalmente (al menos) Object, super.whatever() siempre se referirá a un método en la superclase. Pero, ¿qué pasa si tu clase solo se extiende Object - ¿a qué se referiría super.super entonces? ¿Cómo debe manejarse ese comportamiento - un error del compilador, un NullPointer, etc.?

Creo que la razón principal por la que esto no está permitido es que viola la encapsulación, pero esto también podría ser una pequeña razón.

 7
Author: matt b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-25 15:34:04

Creo que si sobrescribes un método y quieres toda la versión de super-clase de él (como, digamos para equals), entonces prácticamente siempre quieres llamar a la versión de superclase directa primero, que llamará a su versión de superclase a su vez si lo desea.

Creo que solo rara vez tiene sentido (si es que tiene sentido. no puedo pensar en un caso en el que lo haga) para llamar a alguna versión arbitraria de superclase de un método. No se si eso es posible en Java. Se puede hacer en C++:

this->ReallyTheBase::foo();
 3
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-25 15:14:41

Supongo, porque no se usa tan a menudo. La única razón por la que pude verlo es si su padre directo ha anulado alguna funcionalidad y está tratando de restaurarla a la original.

Lo que me parece estar en contra de los principios OO, ya que el padre directo de la clase debe estar más estrechamente relacionado con su clase que el abuelo.

 2
Author: Powerlord,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-25 15:16:12

Yo pondría el super.super cuerpo método en otro método, si es posible

class SuperSuperClass {
    public String toString() {
        return DescribeMe();
    }

    protected String DescribeMe() {
        return "I am super super";
    }
}

class SuperClass extends SuperSuperClass {
    public String toString() {
        return "I am super";
    }
}

class ChildClass extends SuperClass {
    public String toString() {
        return DescribeMe();
    }
}

O si no puedes cambiar la clase super-super, puedes probar esto:

class SuperSuperClass {
    public String toString() {
        return "I am super super";
    }
}

class SuperClass extends SuperSuperClass {
    public String toString() {
        return DescribeMe(super.toString());
    }

    protected String DescribeMe(string fromSuper) {
        return "I am super";
    }
}

class ChildClass extends SuperClass {
    protected String DescribeMe(string fromSuper) {
        return fromSuper;
    }
}

En ambos casos, el

new ChildClass().toString();

Resultados para "I am super super"

 2
Author: xMichal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-29 12:32:46

Parece ser posible al menos obtener la clase de la superclase de la superclase, aunque no necesariamente la instancia de la misma, usando reflexión; si esto podría ser útil, por favor considere el Javadoc en http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()

 1
Author: George Jempty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-02 20:22:11
public class A {

     @Override
     public String toString() {
          return "A";
     }

}


public class B extends A {

     @Override
     public String toString() {
          return "B";
     }

}

public class C extends B {

     @Override
     public String toString() {
          return "C";
     }

}


public class D extends C {

     @Override
     public String toString() {
          String result = "";
          try {
                result = this.getClass().getSuperclass().getSuperclass().getSuperclass().newInstance().toString();
          } catch (InstantiationException ex) {
                Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
          } catch (IllegalAccessException ex) {
                Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
          }
          return result;
     }

}

public class Main {

     public static void main(String... args) {
          D d = new D();
          System.out.println(d);

     }
}

Ejecutar: Un BUILD SUCCESSFUL (tiempo total: 0 segundos)

 1
Author: Boris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-20 19:59:49

He tenido situaciones como estas cuando la arquitectura es construir una funcionalidad común en una CustomBaseClass común que implementa en nombre de varias clases derivadas. Sin embargo, necesitamos eludir la lógica común para un método específico para una clase derivada específica. En tales casos, debemos usar un super.superusuario.Implementación de methodX.

Logramos esto introduciendo un miembro booleano en la CustomBaseClass, que se puede usar para diferir selectivamente la implementación personalizada y ceder a implementación del marco por defecto cuando sea conveniente.

        ...
        FrameworkBaseClass (....) extends...
        {
           methodA(...){...}
           methodB(...){...}
        ...
           methodX(...)
        ...
           methodN(...){...}

        }
        /* CustomBaseClass overrides default framework functionality for benefit of several derived classes.*/
        CustomBaseClass(...) extends FrameworkBaseClass 
        {
        private boolean skipMethodX=false; 
        /* implement accessors isSkipMethodX() and setSkipMethodX(boolean)*/

           methodA(...){...}
           methodB(...){...}
        ...
           methodN(...){...}

           methodX(...){
                  if (isSkipMethodX()) {
                       setSKipMethodX(false);
                       super.methodX(...);
                       return;
                       }
                   ... //common method logic
            }
        }

        DerivedClass1(...) extends CustomBaseClass
        DerivedClass2(...) extends CustomBaseClass 
        ...
        DerivedClassN(...) extends CustomBaseClass...

        DerivedClassX(...) extends CustomBaseClass...
        {
           methodX(...){
                  super.setSKipMethodX(true);
                  super.methodX(...);
                       }
        }

Sin embargo, con buenos principios de arquitectura seguidos tanto en framework como en app, podríamos evitar este tipo de situaciones fácilmente, utilizando el enfoque hasA, en lugar del enfoque isA. Pero en todo momento no es muy práctico esperar una arquitectura bien diseñada en su lugar, y por lo tanto la necesidad de alejarse de principios de diseño sólidos e introducir hacks como este. Sólo mis 2 centavos...

 1
Author: Ganesh Iyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-27 05:51:35

@Jon Skeet Bonita explicación. IMO si alguien quiere llamar super.super método entonces uno debe querer ignorar el comportamiento del padre inmediato, pero desea acceder al comportamiento del padre mayor. Esto se puede lograr a través de la instancia de. Como el siguiente código

public class A {
    protected void printClass() {
        System.out.println("In A Class");
    }
}

public class B extends A {

    @Override
    protected void printClass() {
        if (!(this instanceof C)) {
            System.out.println("In B Class");
        }
        super.printClass();
    }
}

public class C extends B {
    @Override
    protected void printClass() {
        System.out.println("In C Class");
        super.printClass();
    }
}

Aquí está la clase de controlador,

public class Driver {
    public static void main(String[] args) {
        C c = new C();
        c.printClass();
    }
}

La salida de esto será

In C Class
In A Class

El comportamiento de Clase B printClass será ignorado en este caso. No estoy seguro de si esto es un ideal o una buena práctica para lograr super.super, pero aún así está funcionando.

 1
Author: Sanjay Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-04 06:18:10

Si crees que vas a necesitar la superclase, podrías referenciarla en una variable para esa clase. Por ejemplo:

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;
  }
}

Debe imprimir:

2
1
0
 0
Author: Ashtheking,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-20 14:26:15

IMO, es una forma limpia de lograr super.super.sayYourName() comportamiento en 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);
    }
}

Salida:

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

 0
Author: Yakov Fain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-13 09:48:27

Llamada de super.superusuario.method () tiene sentido cuando no puedes cambiar el código de la clase base. Esto sucede a menudo cuando está extendiendo una biblioteca existente.

Pregúntate primero, ¿por qué estás extendiendo esa clase? Si la respuesta es "porque no puedo cambiarlo", entonces puede crear el paquete exacto y la clase en su aplicación, y reescribir el método travieso o crear delegado:

package com.company.application;

public class OneYouWantExtend extends OneThatContainsDesiredMethod {

    // one way is to rewrite method() to call super.method() only or 
    // to doStuff() and then call super.method()

    public void method() {
        if (isDoStuff()) {
            // do stuff
        }
        super.method();
    }

    protected abstract boolean isDoStuff();


    // second way is to define methodDelegate() that will call hidden super.method()

    public void methodDelegate() {
        super.method();
    }
    ...
}

public class OneThatContainsDesiredMethod {

    public void method() {...}
    ...
}

Por ejemplo, puede crear org.springframework.prueba.contexto.junit4.SpringJUnit4ClassRunner clase en su aplicación por lo que esta clase debe cargarse antes de la real de jar. A continuación, reescriba métodos o constructores.

Atención: Este es un truco absoluto, y no se recomienda su uso, pero está FUNCIONANDO! El uso de este enfoque es peligroso debido a posibles problemas con los cargadores de clase. También esto puede causar problemas cada vez que actualice la biblioteca que contiene la clase sobrescrita.

 0
Author: ruruskyi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-16 15:00:10

Creo que este es un problema que rompe el acuerdo de herencia.
Al extender una clase usted obedece / acepta su comportamiento, características
Mientras que al llamar super.super.method(), quieres romper tu propio acuerdo de obediencia.

Simplemente no puedes elegir entre la superclase.

Sin embargo, puede haber situaciones en las que sienta la necesidad de llamar a super.super.method() - por lo general, una mala señal de diseño, en su código o en el código que hereda !
Si el super y super super las clases no se pueden refactorizar (algún código heredado), luego optan por la composición sobre la herencia.

Ruptura de encapsulación es cuando @Override algunos métodos rompiendo el código encapsulado. Los métodos diseñados para no ser anulados están marcados final .

 0
Author: DayaMoon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-09 08:13:39

En C# puedes llamar a un método de cualquier ancestro de esta manera:

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();
    }

También puedes hacer esto en Delphi:

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

Pero en Java se puede hacer tal enfoque solo por algún engranaje. Una forma posible es:

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.Salida de resultado DoIt ():

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
 0
Author: D.Motyl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-07 19:56:51

Mira este proyecto de Github, especialmente la variable objectHandle. Este proyecto muestra cómo llamar de manera real y precisa al método de abuelos en un nieto.

En caso de que el enlace se rompa, aquí está el código:

import lombok.val;
import org.junit.Assert;
import org.junit.Test;

import java.lang.invoke.*;

/*
Your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should.
Please don't actually do this... :P
*/
public class ImplLookupTest {
    private MethodHandles.Lookup getImplLookup() throws NoSuchFieldException, IllegalAccessException {
        val field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
        field.setAccessible(true);
        return (MethodHandles.Lookup) field.get(null);
    }

    @Test
    public void test() throws Throwable {
        val lookup = getImplLookup();
        val baseHandle = lookup.findSpecial(Base.class, "toString",
            MethodType.methodType(String.class),
            Sub.class);
        val objectHandle = lookup.findSpecial(Object.class, "toString",
            MethodType.methodType(String.class),
            // Must use Base.class here for this reference to call Object's toString
            Base.class);
        val sub = new Sub();
        Assert.assertEquals("Sub", sub.toString());
        Assert.assertEquals("Base", baseHandle.invoke(sub));
        Assert.assertEquals(toString(sub), objectHandle.invoke(sub));
    }

    private static String toString(Object o) {
        return o.getClass().getName() + "@" + Integer.toHexString(o.hashCode());
    }

    public class Sub extends Base {
        @Override
        public String toString() {
            return "Sub";
        }
    }

    public class Base {
        @Override
        public String toString() {
            return "Base";
        }
    }
}

Feliz Codificación!!!!

 0
Author: kyay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-15 16:48:28

Es simplemente fácil de hacer. Por ejemplo:

Subclase C de B y subclase B de A. Ambas tienen el método Nomodo() por ejemplo.

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();
}

}

La clase pública C se extiende 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");
}

}

Ejecutar la salida de clase C será: Clase A Clase C

En lugar de salida: Clase A Clase B Clase C

 -1
Author: user2490562,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-16 12:08:56
public class SubSubClass extends SubClass {

    @Override
    public void print() {
        super.superPrint();
    }

    public static void main(String[] args) {
        new SubSubClass().print();
    }
}

class SuperClass {

    public void print() {
        System.out.println("Printed in the GrandDad");
    }
}

class SubClass extends SuperClass {

    public void superPrint() {
        super.print();
    }
}

Salida: Impreso en el abuelo

 -1
Author: Andrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-17 05:48:36