2010-08-11 129 views
31

比方说,我有三个类A,B和C超级调用父类方法

  • B扩展一个
  • ç延伸乙

所有定义一个public void foo()方法。

现在来自C的foo()方法我想调用A的foo()方法(不是它的父B的方法,而是超级超类A的方法)。

我试过super.super.foo();,但它的语法无效。 我该如何做到这一点?

+1

正因为有人要问,为什么C扩展B,如果你似乎希望它直接扩展A? (我想还有其他部分你依赖于B的功能,或者其他东西) – 2010-08-11 07:46:25

+0

只有在B没有覆盖A的foo()时,才能使用super.foo()从C调用A的foo()。 – YoK 2010-08-11 08:02:25

+1

_Effective Java第2版,第16项:赞成继承inheritance_。另外,检查装饰者模式;它可能更适合您的需要。 – polygenelubricants 2010-08-11 08:47:58

回答

30

你甚至不能使用反射。像

Class superSuperClass = this.getClass().getSuperclass().getSuperclass(); 
superSuperClass.getMethod("foo").invoke(this); 

东西会导致InvocationTargetException,因为即使你呼吁superSuperClass foo的方法中,它仍然会使用C.foo()当您指定的调用“这个”。这是所有Java方法都是虚拟方法的结果。

看来你需要B类的帮助(例如定义一个superFoo(){ super.foo(); }方法)。

也就是说,如果您尝试这样的设计,看起来像是一个设计问题,所以给我们一些背景会有帮助:为什么您需要这样做?

+1

这不是我的要求。我只是想尽一切办法继承和继承这个问题。谢谢..我得到了答案 – Harish 2010-08-19 06:18:40

+0

嗯,我需要这样做,因为超类以一种我不想要的方式覆盖超级超类...它是一个库...所以我想打电话给超级超类超类...也许采取超级超类的方法的源代码,重写再次解决这个问题? – xdevs23 2016-03-15 15:43:08

+0

当然,你可以在你的方法中编写你想要的东西,所以在这种情况下,复制代码应该可行。但是,如果super-super-class在'foo()'中使用私有或包私有字段或方法,则需要反射才能访问这些字段或方法(当然,如果安全管理器已安装,则不幸运)。此外,如果最初的'foo()'代码自己调用'super',它也不起作用。 – Landei 2016-03-16 16:56:55

0

这是不可能的,我们仅限于调用超类的实现。

+0

(我太被亚伦现在删除的答案留下深刻的印象我在发布两秒后删除了我的内容;) - 删除了它,即使现在有更好的答案) – 2010-08-11 08:32:04

19

你不能 - 因为它会破坏封装。

你可以调用你的超类的方法,因为它假定你知道什么会破坏你自己的类中的封装,并避免这种情况......但是你不知道你的超类执行什么规则 - 所以你不能绕过这里的实现。

+0

奇怪..我记得有一种方法可以调用Object。toString()即使toString()被超类重载。但是'Type.this'不能编译。 : -/ – 2010-08-11 07:34:20

+1

@Aaron:我不确定Object.toString() - 你在想'System.identityHashCode'吗? – 2010-08-11 07:35:24

+0

从来没有使用过,我很确定它是toString()。 Object.super.toString()也不起作用。也许这是Java早期版本中的一个错误。 – 2010-08-11 07:39:03

3

你不能以简单的方式做到这一点。

这是我认为你可以这样做:

有一个布尔在您的类B.现在,您必须调用B的由C foo的喜欢[super foo]但这样做在此之前设定的布尔为true。现在在B的foo中检查bool是否为真,然后不要执行任何步骤,只需调用A的foo。

希望这会有所帮助。

+6

这是最疯狂的Java破解:) – 2010-08-11 07:40:38

+2

Jon Skeet的答案是最好的:这种功能不应该启用,因为它打破封装。我们应该解决_WHY_问题,而不是解决_HOW_做这样的事情,那么任何人都会想要做这样的事情(并且因违反OOP原则而撕裂这个论点)。 – polygenelubricants 2010-08-11 07:41:49

+2

@Nikita Rybak:人们要求不应该被问到的事情。因此,不应该给出的答案;) – 2010-08-11 07:42:38

0

smell东西很腥。

你确定你不只是推动信封太“只是因为你应该能够做到这一点”?你确定这是你可以得到的最好的设计模式吗?你有没有尝试重构它?

0

我有一个问题,超类会调用被覆盖的顶级方法。 这是我的解决方法...

//这会失败致电超类方法为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(); 
} 

//这保证了RIGHT SUPERCLASS方法被称为 //公有方法只调用私有方法,因此所有公共方法可以被覆盖而不影响超类的功能。

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

我希望这有助于。 :)

+0

这实际上并没有回答这个问题。请重读这个问题。 – Aboutblank 2013-04-16 16:38:48

0

使用反射API之前,请考虑它的成本。

这很容易做到。例如:

B的B子类和B子类的A子类。三者都有方法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类

2

引述先前的回答:“你可以” t - 因为它会破坏封装。“我想补充一点:

但是,有一个角落的情况下,你可以,即如果方法是staticpublicprotected)。你不能overwrite the static method

有一个public static方法是微不足道的证明你确实可以做到这一点。

但对于protected,您需要从您的某个方法中对继承路径中的任何超类执行强制转换,并调用该超类方法。

这是角落情况下,我在我的答案探索:

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

答案依然还是没有,只是想表明的情况下就可以了,虽然它可能会没有任何意义和只是一个练习。

2

是的,你可以做到这一点。这是一个黑客。尽量不要这样设计你的程序。

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

    } 
} 
+0

这就是所谓的控制反转! – 2018-01-29 01:44:18