Java中被覆盖的父类方法还可以调用吗?为什么C++可以调用?{讨论}{技术}{Java,C++}

516 views
Skip to first unread message

BNU ACMer

unread,
Jun 21, 2009, 11:01:49 AM6/21/09
to TopLanguage
Java中被覆盖的父类方法还可以调用吗?
当我问这个问题时,别人的第一反应是:有这种需求吗?我举一个需求的例子:
Java的Object类的 hashCode方法是返回的这个对象的内存地址。
而所有类都是继承于Object类的,但是大多覆盖了hashCode方法。有一次为了分析JVM,
我就需要看一看两个Integer对象的内存地址情况。于是我发现怎么都不能调出父类Object的hashCode方法。
最后我找到了一个方法:System.identityHashCode(Object x) 方法,可以打印出内存地址。结果查源码时,发现此方法的
实现是用的JNI.

那么,Java真的就不能调用父类已经被覆盖的方法了吗?

如果不能调用。更进一步,我发现C++可以很方便地调用父类的被覆盖的方法。代码如下。那么,从设计上,为什么C++可以允许这样调,而Java不能
呢?
#include <stdio.h>

class A
{
public:
virtual void say() {
printf("in function A\n");
}
};

class B : public A
{
public:
virtual void say() {
printf("in function B\n");
}
};

int main() {
A * a = new B();
a->say();
a->A::say();

getchar();
return 0;
}

Yu-zhong shen

unread,
Jun 21, 2009, 10:31:27 PM6/21/09
to pon...@googlegroups.com
应该是因为java类全都是虚函数的关系。

c++是通过显示指定一个父类方法(A::xxx)达到调用目的,如果也是虚函数的话,就和java一样效果。

不知道java能不能显示指定父类方法。

Jay True

unread,
Jun 21, 2009, 10:50:28 PM6/21/09
to pon...@googlegroups.com
super ,吧

2009/6/22 Yu-zhong shen <slavi...@gmail.com>

应该是因为java类全都是虚函数的关系。

c++是通过显示指定一个父类方法(A::xxx)达到调用目的,如果也是虚函数的话,就和java一样效果。

不知道java能不能显示指定父类方法。



--
歌词唱清楚,不是周杰伦
Home Page: http://glacjay.is-a-geek.org/blog/

cdredfox

unread,
Jun 21, 2009, 10:54:54 PM6/21/09
to pon...@googlegroups.com
java 是可以调用父类的被覆盖的方法的。用关键字super

2009/6/22 Jay True <gla...@gmail.com>:

Bruce Khereid

unread,
Jun 22, 2009, 1:31:49 AM6/22/09
to pon...@googlegroups.com
据我所知,只能由它的直接子类来调用,通过 super 关键字。

在我看来,在概念上,Java 里的“方法”是“类”的一部分,类的实现可以全权决定如何响应特定的“调用”,而“调用”只通过一个字符串——方法名——被识别;任何其它角色——甚至包括子类——都不可以强制让它以不同的方式——即使是已覆盖的父类的方式——响应。子类认为自己的 hashCode 调用的语意不和 Object 所描述的一样,那么 Object.hashCode 对它就不再有任何意义了。

有所不同的是,C++ 的类来自结构体,更多是一种“集成”的含义。它认为“函数”是些自主的实体,它们被组织在某种“命名空间”里,“类”把一些特定的函数“集成”起来。这样,外界的代码也可以选择调用哪个具体的函数实现。

类似的区别还有,Java 在实现多个接口时无法区分这来自不同接口的同名同签名方法。

2009/6/22 cdredfox <cdre...@gmail.com>

Alan Gao

unread,
Jun 22, 2009, 12:00:08 AM6/22/09
to pon...@googlegroups.com
Java中如果要从内部访问父类中被被覆盖的方法,是用super关键词:

如:

public class A {
   public void aMethod() {

}

public class B extends A {
   public void aMethod() {
         super.aMethod()    //内部调用父类方法。
   }
}

但从外部是无法调用非static方法的,即使是cast成父类也不行:
如:
B b = new B();
((A)b).aMethod();    //将还是调用B中的方法

这个特性是Java和C之间在设计上的区别,Java是有意这样设计的,Thinking in Java中有讲解,可以去看一下。(具体章节不记得了)

我在网上找到了另一个人的解释:


All method invocation in Java is done polymorphically--based on the
true type of the instance, not on the declared type of the variable or
value through which the invocation is made. Casting changes only the
static or compile-time type associated with a value, not the real type
of the instance to which the variable or value refers.


Alan Gao


2009/6/22 BNU ACMer <tangq...@gmail.com>

Alan Gao

unread,
Jun 22, 2009, 12:38:33 AM6/22/09
to pon...@googlegroups.com
再接着我之前的回复说说我的想法。 因为Java是一种严格的面向对象的语言,而C++想对来说比较灵活,严格地说,C++的一些特点打破了一些OO语言的逻辑性。细想想看,Java不允许从外部防问父类被覆盖的方法是有其逻辑性的,举个例子:

public interface Shape {
     Color sayYourColor() {return WHITE};
}

public class Rectangle implements Shape {
     Color sayYourColor() {
         return YELLO;
     }
}

public class Square extends Rectangle {
     Color sayYourColor() {
         return BLUE;
     }
}

正方形是长方形的一个子类。形状定义了一个方法来返回其颜色,当我们创建了一个正方形的实例:Square s = new Square();
调用s.sayYourColor();时,返回的是蓝色是正确的。 但如果调用((Rectangle)s).sayYourColor()之后返回黄色显然是不和逻辑的,因为我们创建是一个蓝色正方形。

你举的例子一个实际的编程应用方面的例子,而面向对象思想是抽象的概念,Java只是严格的执行了概念中的要求。

Alan Gao

BNU ACMer

unread,
Jun 22, 2009, 1:05:30 AM6/22/09
to TopLanguage
在子类中当然是可以用super关键字来调用。我是说在外部调用而不是在子类中。


On Jun 22, 10:54 am, cdredfox <cdred...@gmail.com> wrote:
> java 是可以调用父类的被覆盖的方法的。用关键字super
>

> 2009/6/22 Jay True <glac...@gmail.com>:
>
>
>
> > super ,吧
>
> > 2009/6/22 Yu-zhong shen <slaviks...@gmail.com>


>
> >> 应该是因为java类全都是虚函数的关系。
>
> >> c++是通过显示指定一个父类方法(A::xxx)达到调用目的,如果也是虚函数的话,就和java一样效果。
>
> >> 不知道java能不能显示指定父类方法。
>
> > --
> > 歌词唱清楚,不是周杰伦

> > Home Page:http://glacjay.is-a-geek.org/blog/- Hide quoted text -
>
> - Show quoted text -

BNU ACMer

unread,
Jun 22, 2009, 6:35:01 AM6/22/09
to TopLanguage
嗯,很受启发,谢谢:)

On Jun 22, 12:38 pm, Alan Gao <cgao...@gmail.com> wrote:
> 再接着我之前的回复说说我的想法。

> 因为Java是一种严格的面向对象的语言,而C++想对来说比较灵活,严格地说,C++的一些特点打破了一些OO语言的逻辑性。细想想看,Java不允许从外部-防问父类被覆盖的方法是有其逻辑性的,举个例子:

abracadabra

unread,
Jun 23, 2009, 11:32:28 AM6/23/09
to TopLanguage
MS捣鼓出来一个__super关键字:
http://msdn.microsoft.com/en-us/library/94dw1w7x(VS.80).aspx
的确比dynamic_cast方便一点点

Bearice Ren

unread,
Jun 23, 2009, 11:47:00 AM6/23/09
to pon...@googlegroups.com
Java也不是说绝对不可以,耍一些字节码级别的trick也是可以从外部调用被覆盖的方法甚至父类的父类中的方法的,但是这种做法不被推荐的原因除了破坏了覆盖的意义外,还无形间加重了代码的耦合关系(If a such feature would exists it should be avoided because it will create an highly coupling between the class and its super super class. )

可以看一下这个mail:http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/cb5bcec527a460e/813036e8c85e556c?q=#813036e8c85e556c

2009/6/22 Yu-zhong shen <slavi...@gmail.com>

应该是因为java类全都是虚函数的关系。

c++是通过显示指定一个父类方法(A::xxx)达到调用目的,如果也是虚函数的话,就和java一样效果。

不知道java能不能显示指定父类方法。



--
以上内容完全是复制粘贴,本人并不明白其意思,故本人不对以上内容负法律责任,请不要跨省追捕。要详查请自己联系原作者,谢谢!
Bearice@Guilin, Guangxi, China
一头宅熊、坚定的反Microsoft主义者、开源支持者、P2P拥护者; Google粉,FF粉,桂林米粉;翻墙运动爱好者,以及アナキズム;马勒戈壁驻桂办事处干事;最近添加眼镜属性(据说原因是很萌)。
Reply all
Reply to author
Forward
0 new messages