2010-06-25 68 views
24

我有一个类扩展了一个我需要覆盖的类,但是我需要调用该类的父类。因为我不能调用超级,因为这将执行直接父母什么是获得我的父类的父母的最佳方式?Java:你如何访问两个级别的父类方法?

我确定这是一个基本问题,但是自从我一直在做任何java以来​​,它已经有一段时间了。

class A 
{ 
public void myMethod() 
{ /* ... */ } 
} 

class B extends A 
{ 
public void myMethod() 
{ /* Another code */ } 
} 

class C extends B 
{ 
I need to call Class A here 
{ /* Another code */ } 
} 
+1

几乎总是使用超级是不好的形式。唯一可能的例外就是过度方法称之为被忽略。在这种情况下,最好引入一个抽象或无所事事的方法,并用“原始”方法取代最终方法。但是这意味着你只能得到一杆。深厚的heirarchies是坏的反正... – 2010-06-25 13:07:08

+0

可能重复的[Java如何调用方法的祖父?](http://stackoverflow.com/questions/2584377/java-how-to-call-method-of-grand-父母)。也有关http://stackoverflow.com/questions/586363/why-is-super-super-method-not-allowed-in-java – finnw 2010-06-25 19:39:28

回答

27

你别:它违反了封装。

可以说“不,我不想要我自己的行为 - 我想要我父母的行为”,因为假设您只有在正确维护自己的状态时才会这样做。

但是,您无法绕过父母的行为 - 这将阻止其强制执行自己的一致性。如果父类想要允许您直接调用祖父方法,它可以通过单独的方法公开该方法......但这取决于父类。

+0

谢谢,我明白了。我想我可能正在接近这个错误的方式。 – 2010-06-25 12:58:14

9

你不能因为它已被覆盖B.没有A内的情况下

的事情是,你要调用的类A的方法,但是从实例?你已经实例化了C,它是一个拥有自己和从B继承的方法的类。如果B重写A的一个方法,则不能从C访问它,因为方法本身属于C(不是方法B的,它一直延续下来,现在它在C)

可能的解决方法:

B不覆盖myMethod()

C接收到A的实例,并将其保存为一个类属性。

myMethod()在一个是静态的,你用A.myMethod()(我不推荐)

+0

谢谢,我看到我做错了,但谢谢你的解释。它帮助我理解。 – 2010-06-25 13:00:39

1

再说什么pakore回答,你也可以连锁super.myMethod()电话是否适合你。您将在B.

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

class B extends A { 
    public void myMethod() { 
    .... 
    super.myMethod(); 
    .... 
    } 
} 

class C extends B { 
    public void myMethod() { 
    .... 
    super.myMethod(); //calls B who calls A 
    .... 
    } 
} 

你最终会从呼叫myMethod的调用myMethod()从A从myMethod(),但间接地......如果你的作品。

+0

只有当您希望B.myMethod()与A.myMethod()完全相同时才会起作用,这会导致以下问题:为什么地狱会在第一次覆盖它? :) – pakore 2010-06-25 12:59:29

+0

@pakore:对不起...简单的例子。当你需要的时候,根据一些条件,标志等等,你可以调用super.myMethod。我将这个例子稍微改了一点,以使其更清晰 – 2010-06-25 13:03:02

+0

是的,我认为你的意思是你现在已经更新了。请记住,您的解决方案与从C调用A.myMethod()不同,因为B.myMethod()正在做其他事情,也许C不希望他们完成。 C只是想让A.myMethod()完成,而不是一两个。这就是为什么我说只有在A.myMethod()=== B.myMethod()时才有效,而且它的覆盖没有意义:)。 – pakore 2010-06-25 13:07:49

0

您不能直接调用A的方法。在我遇到这种情况的少数案例中,解决方案是在A中添加一个方法来公开它的实现。例如。

class A 
{ 
    public myMethod() { 
     doAMyMethod(); 
    } 

    void doAMyMethod() { 
     // what A want's on doMyMethod, but now it's available 
     // as a separately identifiable method 
    } 
} 

class C extends B 
{ 
    public void someStuff() { 
     this.doAMyMethod(); 
    } 
} 

该方案将公共接口(doMyMethod)从实现(doAMyMethod)中分离出来。继承取决于实现细节,所以这不是严格的那么糟糕,但我会尽量避免它,因为它会在A和C之间实现紧密耦合。

6

你在问什么是坏的练习,你所说的是C不是B,而是A.你需要做的是从C继承A.然后你可以调用super。

如果不是这是唯一的办法......

public String A() 
{ 
String s = "hello"; 
return s; 
} 

public String B() 
{ 
String str = super.A(); 
return str; 
} 

public String C() 
{ 
String s = super.B(); 
return s; 
} 
+1

谢谢,我发现我这样做是错误的,必须考虑更好的解决方案。我可能不必访问那个盛大的父母方法去做我想做的事。 – 2010-06-25 12:58:59

0

我这种情况做的是:

使C类中的A类的对象,并访问A类存在。 该实施例阐明了其更多的细节:

class A{ 
int a; 
} 
class B extends A{ 
int a; 
} 
class C extends B{ 
int a; 
A obj = new A(); 
public void setData(int p,int q, int r) { 

this.a = p; // points to it's own class 
super.a = q;// points to one up level class i.e in this case class B 
obj.a = r; // obj points the class A 
} 
public void getData() { 
    System.out.println("A class a: "+ obj.a); 
    System.out.println("B class a: "+ super.a); 
    System.out.println("C class a: "+this.a); 
} 
} 

public class MultiLevelInheritanceSuper { 

public static void main(String args[]){ 
    C2 obj = new C2(); 
    obj.setData(10, 20, 30); 
    obj.getData(); 

} 

}

本实施例的输出是:

A class a: 30 
B class a: 20 
C class a: 10