简体   繁体   English

为什么是 super.super.method(); 在 Java 中不允许?

[英]Why is super.super.method(); not allowed in Java?

I read this question and thought that would easily be solved (not that it isn't solvable without) if one could write:我读了这个问题,并认为如果有人可以写,这很容易解决(并不是说没有它就无法解决):

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

I'm not sure if it is useful in many cases, but I wonder why it isn't and if something like this exists in other languages.我不确定它在很多情况下是否有用,但我想知道为什么它没有用,以及其他语言中是否存在类似的东西。

What do you guys think?你们有什么感想?

EDIT: To clarify: yes I know, that's impossible in Java and I don't really miss it.编辑:澄清一下:是的,我知道,在 Java 中这是不可能的,我并没有真正想念它。 This is nothing I expected to work and was surprised getting a compiler error.这不是我期望的工作,并且很惊讶得到编译器错误。 I just had the idea and like to discuss it.我只是有这个想法,并喜欢讨论它。

It violates encapsulation.它违反了封装。 You shouldn't be able to bypass the parent class's behaviour.您不应该能够绕过父类的行为。 It makes sense to sometimes be able to bypass your own class's behaviour (particularly from within the same method) but not your parent's.有时能够绕过您自己的类的行为(尤其是在同一方法中)而不是您父母的行为是有意义的。 For example, suppose we have a base "collection of items", a subclass representing "a collection of red items" and a subclass of that representing "a collection of big red items".例如,假设我们有一个基础“项目集合”,一个表示“红色项目集合”的子类和一个表示“大红色项目集合”的子类。 It makes sense to have:拥有以下内容是有意义的:

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

That's fine - RedItems can always be confident that the items it contains are all red.没关系 - RedItems 始终可以确信它包含的项目都是红色的。 Now suppose we were able to call super.super.add():现在假设我们能够调用 super.super.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);
    }
}

Now we could add whatever we like, and the invariant in RedItems is broken.现在我们可以添加任何我们喜欢的东西, RedItems中的不变量被破坏了。

Does that make sense?那有意义吗?

I think Jon Skeet has the correct answer.我认为 Jon Skeet 有正确的答案。 I'd just like to add that you can access shadowed variables from superclasses of superclasses by casting this :我只想补充一点,您可以通过强制转换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();
        }
}

which produces the output:产生 output:

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

(example from the JLS ) (来自JLS的示例)

However, this doesn't work for method calls because method calls are determined based on the runtime type of the object.但是,这不适用于方法调用,因为方法调用是根据 object 的运行时类型确定的。

I think the following code allow to use super.super...super.method() in most case.我认为以下代码允许在大多数情况下使用 super.super...super.method() 。 (even if it's uggly to do that) (即使这样做很丑陋)

In short简而言之

  1. create temporary instance of ancestor type创建祖先类型的临时实例
  2. copy values of fields from original object to temporary one将字段的值从原始object 复制到临时字段
  3. invoke target method on temporary object在临时 object 上调用目标方法
  4. copy modified values back to original object将修改后的值复制回原始 object

Usage:用法:

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

I don't have enough reputation to comment so I will add this to the other answers.我没有足够的声誉发表评论,所以我会将其添加到其他答案中。

Jon Skeet answers excellently, with a beautiful example. Jon Skeet 的回答非常出色,举了一个漂亮的例子。 Matt B has a point: not all superclasses have supers. Matt B 有一点:不是所有的超类都有超类。 Your code would break if you called a super of a super that had no super.如果您调用没有超级的超级的超级,您的代码将会中断。

Object oriented programming (which Java is) is all about objects, not functions. Object 面向编程(Java 是)都是关于对象的,而不是函数。 If you want task oriented programming, choose C++ or something else.如果您想要面向任务的编程,请选择 C++ 或其他东西。 If your object doesn't fit in it's super class, then you need to add it to the "grandparent class", create a new class, or find another super it does fit into.如果您的 object 不适合它的超级 class,那么您需要将其添加到“祖父类”,创建一个新的 class,或者找到另一个适合的超级。

Personally, I have found this limitation to be one of Java's greatest strengths.就个人而言,我发现这种限制是 Java 的最大优势之一。 Code is somewhat rigid compared to other languages I've used, but I always know what to expect.与我使用的其他语言相比,代码有些僵化,但我总是知道会发生什么。 This helps with the "simple and familiar" goal of Java.这有助于实现 Java 的“简单而熟悉”的目标。 In my mind, calling super.super is not simple or familiar.在我看来,调用 super.super 并不简单也不熟悉。 Perhaps the developers felt the same?也许开发人员也有同感?

There's some good reasons to do this.这样做有一些很好的理由。 You might have a subclass which has a method which is implemented incorrectly, but the parent method is implemented correctly.您可能有一个子类,它的方法实现不正确,但父方法实现正确。 Because it belongs to a third party library, you might be unable/unwilling to change the source.因为它属于第三方库,您可能无法/不愿意更改源。 In this case, you want to create a subclass but override one method to call the super.super method.在这种情况下,您要创建一个子类,但要重写一个方法来调用 super.super 方法。

As shown by some other posters, it is possible to do this through reflection, but it should be possible to do something like正如其他一些海报所示,可以通过反射来做到这一点,但应该可以做类似的事情

(SuperSuperClass this).theMethod(); (SuperSuperClass this).theMethod();

I'm dealing with this problem right now - the quick fix is to copy and paste the superclass method into the subsubclass method:)我现在正在处理这个问题 - 快速解决方法是将超类方法复制并粘贴到子类方法中:)

In addition to the very good points that others have made, I think there's another reason: what if the superclass does not have a superclass?除了其他人提出的非常好的观点之外,我认为还有另一个原因:如果超类没有超类怎么办?

Since every class naturally extends (at least) Object , super.whatever() will always refer to a method in the superclass.由于每个 class 自然地扩展(至少) Objectsuper.whatever()将始终引用超类中的方法。 But what if your class only extends Object - what would super.super refer to then?但是,如果您的 class 仅扩展Object怎么办 - 那么super.super指的是什么? How should that behavior be handled - a compiler error, a NullPointer, etc?应该如何处理这种行为 - 编译器错误、NullPointer 等?

I think the primary reason why this is not allowed is that it violates encapsulation, but this might be a small reason too.我认为不允许这样做的主要原因是它违反了封装,但这也可能是一个小原因。

I think if you overwrite a method and want to all the super-class version of it (like, say for equals ), then you virtually always want to call the direct superclass version first, which one will call its superclass version in turn if it wants.我认为如果您覆盖一个方法并想要它的所有超类版本(例如,对于equals ),那么您实际上总是希望首先调用直接超类版本,如果它会依次调用它的超类版本想要。

I think it only makes rarely sense (if at all. i can't think of a case where it does) to call some arbitrary superclass' version of a method.我认为调用某个方法的任意超类版本几乎没有意义(如果有的话。我想不出它确实如此)。 I don't know if that is possible at all in Java.我不知道在 Java 中这是否可能。 It can be done in C++:可以在 C++ 中完成:

this->ReallyTheBase::foo();

Look atthis Github project, especially the objectHandle variable.看看这个Github 项目,尤其是 objectHandle 变量。 This project shows how to actually and accurately call the grandparent method on a grandchild.这个项目展示了如何在孙子上实际准确地调用祖父母方法。

Just in case the link gets broken, here is the code:以防万一链接被破坏,这里是代码:

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

Happy Coding!!!!快乐编码!!!!

At a guess, because it's not used that often.猜测一下,因为它不经常使用。 The only reason I could see using it is if your direct parent has overridden some functionality and you're trying to restore it back to the original.我可以看到使用它的唯一原因是如果您的直接父母已经覆盖了某些功能并且您正在尝试将其恢复为原始功能。

Which seems to me to be against OO principles, since the class's direct parent should be more closely related to your class than the grandparent is.在我看来,这违反了 OO 原则,因为与祖父母相比,班级的直接父母应该与您的 class 更密切相关。

@Jon Skeet Nice explanation. @Jon Skeet 很好的解释。 IMO if some one wants to call super.super method then one must be want to ignore the behavior of immediate parent, but want to access the grand parent behavior. IMO 如果有人想调用 super.super 方法,那么必须要忽略直接父母的行为,但要访问祖父母的行为。 This can be achieved through instance Of.这可以通过instance Of来实现。 As below code如下代码

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

Here is driver class,这里是驱动 class,

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

Output of this will be Output 这将是

In C Class
In A Class

Class B printClass behavior will be ignored in this case. Class B printClass 行为在这种情况下将被忽略。 I am not sure about is this a ideal or good practice to achieve super.super, but still it is working.我不确定这是实现 super.super 的理想做法还是好的做法,但它仍然有效。

I would put the super.super method body in another method, if possible如果可能的话,我会将 super.super 方法体放在另一个方法中

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

Or if you cannot change the super-super class, you can try this:或者如果你无法改变超超class,你可以试试这个:

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

In both cases, the在这两种情况下,

new ChildClass().toString();

results to "I am super super"结果“我超级超级”

It would seem to be possible to at least get the class of the superclass's superclass, though not necessarily the instance of it, using reflection;似乎至少可以使用反射获得超类超类的 class ,尽管不一定是它的实例; if this might be useful, please consider the Javadoc at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()如果这可能有用,请考虑http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()上的 Javadoc

I have had situations like these when the architecture is to build common functionality in a common CustomBaseClass which implements on behalf of several derived classes.当架构要在代表多个派生类实现的通用 CustomBaseClass 中构建通用功能时,我遇到过类似的情况。 However, we need to circumvent common logic for specific method for a specific derived class.但是,对于特定派生的 class,我们需要规避特定方法的通用逻辑。 In such cases, we must use a super.super.methodX implementation.在这种情况下,我们必须使用 super.super.methodX 实现。

We achieve this by introducing a boolean member in the CustomBaseClass, which can be used to selectively defer custom implementation and yield to default framework implementation where desirable.我们通过在 CustomBaseClass 中引入 boolean 成员来实现这一点,该成员可用于选择性地推迟自定义实现并在需要时屈服于默认框架实现。

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

However, with good architecture principles followed in framework as well as app, we could avoid such situations easily, by using hasA approach, instead of isA approach.但是,如果在框架和应用程序中遵循良好的架构原则,我们可以通过使用 hasA 方法而不是 isA 方法轻松避免这种情况。 But at all times it is not very practical to expect well designed architecture in place, and hence the need to get away from solid design principles and introduce hacks like this.但在任何时候,期望设计良好的架构都不是很实际,因此需要摆脱坚实的设计原则并引入这样的技巧。 Just my 2 cents...只是我的2美分...

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

     }
}

run: A BUILD SUCCESSFUL (total time: 0 seconds)运行:A BUILD SUCCESSFUL(总时间:0 秒)

Calling of super.super.method() make sense when you can't change code of base class.当您无法更改基本 class 的代码时,调用 super.super.method() 是有意义的。 This often happens when you are extending an existing library.当您扩展现有库时,通常会发生这种情况。

Ask yourself first, why are you extending that class?首先问自己,为什么要扩展 class? If answer is "because I can't change it" then you can create exact package and class in your application, and rewrite naughty method or create delegate:如果答案是“因为我无法更改它”,那么您可以在您的应用程序中创建精确的 package 和 class,并重写顽皮的方法或创建委托:

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

For instance, you can create org.springframework.test.context.junit4.SpringJUnit4ClassRunner class in your application so this class should be loaded before the real one from jar.例如,您可以在您的应用程序中创建org.springframework.test.context.junit4.SpringJUnit4ClassRunner class 所以这个 class 应该在 Z68995FCBF432492D140484D04A9D2AC. Then rewrite methods or constructors.然后重写方法或构造函数。

Attention: This is absolute hack, and it is highly NOT recommended to use but it's WORKING.注意:这是绝对的 hack,强烈不建议使用,但它可以工作。 Using of this approach is dangerous because of possible issues with class loaders.使用这种方法很危险,因为 class 加载程序可能存在问题。 Also this may cause issues each time you will update library that contains overwritten class.每次更新包含被覆盖类的库时,这也可能会导致问题。

I think this is a problem that breaks the inheritance agreement.我认为这是一个破坏 inheritance 协议的问题。
By extending a class you obey / agree its behavior, features通过扩展 class 您遵守/同意其行为、功能
Whilst when calling super.super.method() , you want to break your own obedience agreement.在调用super.super.method()时,您想打破自己的服从协议。

You just cannot cherry pick from the super class .你不能从超级 class中挑选。

However, there may happen situations when you feel the need to call super.super.method() - usually a bad design sign, in your code or in the code you inherit !然而,当你觉得需要调用super.super.method()时,可能会发生这种情况——通常是一个糟糕的设计标志,在你的代码或你继承的代码中!
If the super and super super classes cannot be refactored (some legacy code), then opt for composition over inheritance.如果supersuper super类无法重构(一些遗留代码),则选择 inheritance 上的组合。

Encapsulation breaking is when you @Override some methods by breaking the encapsulated code.封装破坏是当您通过破坏封装的代码来@Override某些方法时。 The methods designed not to be overridden are marked final .设计为不被覆盖的方法被标记为final

It is simply easy to do.这很容易做到。 For instance:例如:

C subclass of B and B subclass of A. Both of three have method methodName() for example. C B 的子类和 A 的 B 子类。这三个都有方法 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");
    }

}

Run class C Output will be: Class A Class C Run class C Output will be: Class A Class C

Instead of output: Class A Class B Class C Instead of output: Class A Class B Class C

In C# you can call a method of any ancestor like this:在 C# 中,您可以像这样调用任何祖先的方法:

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

Also you can do this in Delphi:您也可以在 Delphi 中执行此操作:

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

But in Java you can do such focus only by some gear.但是在 Java 中,您只能通过一些齿轮来进行这种聚焦。 One possible way is:一种可能的方法是:

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() result output: objC.DoIt() 结果 output:

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

The keyword super is just a way to invoke the method in the superclass.关键字 super 只是调用超类中方法的一种方式。 In the Java tutorial: https://docs.oracle.com/javase/tutorial/java/IandI/super.html In the Java tutorial: https://docs.oracle.com/javase/tutorial/java/IandI/super.html

If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super.如果您的方法覆盖了它的超类的方法之一,您可以通过使用关键字 super 来调用被覆盖的方法。

Don't believe that it's a reference of the super object,.!不要相信是超级object的参考,.! No, it's just a keyword to invoke methods in the superclass.不,它只是调用超类中方法的关键字。

Here is an example:这是一个例子:

class Animal {
    public void doSth() {
        System.out.println(this);   // It's a Cat! Not an animal!
        System.out.println("Animal do sth.");
    }
}

class Cat extends Animal {
    public void doSth() {
        System.out.println(this);
        System.out.println("Cat do sth.");
        super.doSth();
    }
}

When you call cat.doSth() , the method doSth() in class Animal will print this and it is a cat.当您调用cat.doSth()时,class Animal中的方法doSth()将打印this并且它是一只猫。

IMO, it's a clean way to achieve super.super.sayYourName() behavior in Java. IMO,这是在 Java 中实现super.super.sayYourName()行为的一种干净的方法。

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

Output: Output:

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

If you think you are going to be needing the superclass, you could reference it in a variable for that class.如果您认为您将需要超类,您可以在该 class 的变量中引用它。 For example:例如:

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

Should print out:应该打印出来:

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

Output: Printed in the GrandDad Output:印在爷爷

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

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