子类继承来的方法为何不访问自己的属性

yuetiantian 2009-07-21 09:58:26
大家好,初学java不久,遇到一个问题。现在有两个类,子类继承了父类的一个方法,并且子类覆盖了父类的一个同名属性。代码如下:
//BaseClass.java
package Example;

public class BaseClass {
String name = "BaseClass";
public String getName(){
return name;
}
public String getInfo(){
return name;
}
}


//SubClass.java
package Example;

public class SubClass extends BaseClass{
String name = "SubClass";
public String getName(){
return name;
}
}

//Test.java
package Example;

public class Test {

public static void main(String[] args) {
BaseClass b = new BaseClass();
SubClass s = new SubClass();

System.out.println(b.getName());
System.out.println(s.getName());

System.out.println(b.getInfo());
System.out.println(s.getInfo());

}

}

运行结果却为:
BaseClass
SubClass
BaseClass
BaseClass
怎么也想不通,为啥子类为何不能打印出自己的name属性,请大家指教!谢谢

...全文
391 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
ArayChou 2009-07-23
  • 打赏
  • 举报
回复
[Quote=引用 1 楼:]现在有两个类,子类继承了父类的一个方法,并且子类覆盖了父类的一个同名属性。
[/Quote]

这个提法是不对的,只有方法才有覆盖(overRide)的说法,属性(字段)是没有覆盖的说发的。无论是public还是private的属性,都不存在覆盖。

如果大家调试一下程序,会发现,在继承树中如果有多个同名的字段,子类的实例里就有多个同名的属性,而不是一个名字的属性只有一个。
ArayChou 2009-07-23
  • 打赏
  • 举报
回复
[Quote=引用 1 楼:]

怎么也想不通,为啥子类为何不能打印出自己的name属性,请大家指教!谢谢
[/Quote]

这是java的规范,没有为什么。

非要说为什么,我只能如下回答:

C++有“许函数”的概念。就是说,在继承过程中,上下级中存在很多overRide的方法。在编译的时候,并不能确定在运行的时候执行哪一个方法。

以搂住的例子来说,编译Test的时候,编译器不知道调用getName(),getInfo()是调用的父类的方法还是子类的方法。所有面向对象的程序最总还是顺序执行。怎么办呢?就引入一个“虚函数”的机制。在运行的时候来决定调用哪一个方法。这个机制就是调用继承树最底层方法。

大家可能要说,可以让编译器扫描所有代码,让他在编译就定下调用哪一个方法。这样的做法有个问题。我们在使用别人写的jar包的时候,别人修改了代码,你就的重新编译一下你所有的东西,这样显然不是我们想要的,java设计者也认为这样不合理,所以就不是这样了。

但是,有虚函数这个概念,却没有“虚属性”,“虚字段”这样的东西。对于字段的引用,直接查找当前类的字段。

另外,只有非private的函数才是许函数,private生命的函数不是许函数。

即:下面的测试代码,输出为Base


package test;

/**
* @author aray
*
*/
class Base {
private void test() {
System.out.println("Base");
}

public void exec() {
test();
}
}

class Sub extends Base {
private void test() {
System.out.println("Sub");
}
}

public class Test {
public static void main(String[] args) {
Sub s = new Sub();
s.exec();
}
}
ltandfyy 2009-07-23
  • 打赏
  • 举报
回复
更正一下,36楼说的对,属性是没有覆盖的概念的,
就是子类中没有与父亲同名的属性,调用的就是父类的,如果有同名的,在没有用super.来指明的情况下,默认调用的是自己。
ltandfyy 2009-07-23
  • 打赏
  • 举报
回复
LZ最后一句:System.out.println(s.getInfo());
子类中没有覆盖getInfo()这个方法,是不是应该调用父类的getInfo()方法?
父类的getInfo()方法中的return name;你说这个name是子类的还是父类的?
如果子类没有覆盖父类的属性,在子类中调用的name是父类的,但父类中的name还能是子类的?LZ有没有搞清楚继承关系是关键,不然再多的解释都白费。只有子类能继承父类的东西,父类本身里的方法所调用的属性必然是其自身的属性或是这个父类的父类,一个父类是怎么能知道将会由哪个子类来继承自己的?又怎么会调用到子类的属性的?
justinavril 2009-07-23
  • 打赏
  • 举报
回复
哎 真是的

方法可以覆盖:覆盖了就按覆盖后的执行,如果没有,就执行父类的方法;
属性无法覆盖,或者说不存在覆盖属性这一说法。
bayougeng 2009-07-22
  • 打赏
  • 举报
回复
我觉得,问题的根源是,子类的name属性并没有覆盖父类的name属性。
我修改了一下代码,运行结果正好印证了我的想法:
public class SubClass extends BaseClass{

SubClass(){
name = "SubClass";
}

public String getName(){
return name;
}
}
为SubClass追加了一个构造方法。然后运行Test。得到如下的结果:
BaseClass
SubClass
BaseClass
SubClass
大家不信的可以自己试试。
Dan1980 2009-07-22
  • 打赏
  • 举报
回复
你的超类应该这么写:


//BaseClass.java
package Example;

public class BaseClass {
String name = "BaseClass";
public String getName(){
return name;
}
public String getInfo(){
return getName();
}
}
Edwin603 2009-07-22
  • 打赏
  • 举报
回复
我的14990544
Edwin603 2009-07-22
  • 打赏
  • 举报
回复
你QQ多少 我语音给你说 不信给你说不明白!
Edwin603 2009-07-22
  • 打赏
  • 举报
回复
天啊JVM 不就是管理内存吗 天啊
yuetiantian 2009-07-22
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 edwin603 的回复:]
引用 25 楼 yuetiantian 的回复:
迄今未知,仍然没有满意的答案出现。

满意答案?
说的够明白了都 你父类定义的方法其中的name 就指你父类的name
千万别说什么覆盖了父类的同名属性 真覆盖了吗? 构造子类对象时 对象里照样有你父类的name 存在在你子类的对象内存中 请问楼主内存懂的多吗?覆盖 是指去掉以前的把新的盖上去 可是 变量根本不是这个效果 在子类对象里 照样有2个name 一个是子类里的 一个是父类里的 你调用父类的方法 那方法 抱歉 他只认识父亲的name 说白了 那个方法里的name 就和父亲类里的name绑在一起了 哪个子类调用这个方法都只能是父类的name 除非你在子类里重写这个方法!
[/Quote]
你说的这个和内存没关系,主要看JVM是如何实现的
virus7581 2009-07-22
  • 打赏
  • 举报
回复
public String getInfo(){
return this.name;
}
说白了,父类的这个方法中默认name为this.name;当你实例化子类对象是,首先会实例化父类对象,那么这里this就是这个父类对象;因此getInfo方法返回的name是父类对象的name,除非你在子类中重写这个方法;
在说白点,就是父类合子类的同名属性name在创建对象时根本是两码事,是两个地址完全不同的变量,而你方法中的this显然是指代父类对象,而不是子类对象
Edwin603 2009-07-22
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 yuetiantian 的回复:]
迄今未知,仍然没有满意的答案出现。
[/Quote]
满意答案?
说的够明白了都 你父类定义的方法其中的name 就指你父类的name
千万别说什么覆盖了父类的同名属性 真覆盖了吗? 构造子类对象时 对象里照样有你父类的name 存在在你子类的对象内存中 请问楼主内存懂的多吗?覆盖 是指去掉以前的把新的盖上去 可是 变量根本不是这个效果 在子类对象里 照样有2个name 一个是子类里的 一个是父类里的 你调用父类的方法 那方法 抱歉 他只认识父亲的name 说白了 那个方法里的name 就和父亲类里的name绑在一起了 哪个子类调用这个方法都只能是父类的name 除非你在子类里重写这个方法!
Edwin603 2009-07-22
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 notlogin 的回复:]
引用 23 楼 edwin603 的回复:
引用 21 楼 notlogin 的回复:
我明白你的意思,按照你的想法 应该
修改父类
public String getInfo(String name) {
this.name=name;
return name;
}
修改主函数
System.out.println(b.getInfo(b.name));
System.out.println(s.getInfo(s.name));
这样你就可以用父类的方法,准确的把你要的值返回去。


我快晕死过去了 人家楼主问的是他的代码的写法和他预期效果不一样的原因
不是问 怎么写就能得到他想要的
现在中国学程序的人 是不是语文都不好 哈哈

我看你也没懂。。。你连他原来的代码都没懂。。。。因为你看不懂我在22楼写的

是不是非要把窗户纸捅的破破的呢?



[/Quote]
懒得和你争辩 等后面的明白人在评价你的代码吧 有点可笑了
你是为了完成楼主的预期效果改的代码 楼主问的是他的代码每得到他预期效果的原因
你那代码太无聊了 我看不懂?您那代码真的好可笑 完全是孩子的思维
yuetiantian 2009-07-22
  • 打赏
  • 举报
回复
迄今未知,仍然没有满意的答案出现。
notlogin 2009-07-22
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 edwin603 的回复:]
引用 21 楼 notlogin 的回复:
我明白你的意思,按照你的想法 应该
修改父类
public String getInfo(String name) {
this.name=name;
return name;
}
修改主函数
System.out.println(b.getInfo(b.name));
System.out.println(s.getInfo(s.name));
这样你就可以用父类的方法,准确的把你要的值返回去。


我快晕死过去了 人家楼主问的是他的代码的写法和他预期效果不一样的原因
不是问 怎么写就能得到他想要的
现在中国学程序的人 是不是语文都不好 哈哈
[/Quote]
我看你也没懂。。。你连他原来的代码都没懂。。。。因为你看不懂我在22楼写的

是不是非要把窗户纸捅的破破的呢?


Edwin603 2009-07-22
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 notlogin 的回复:]
我明白你的意思,按照你的想法 应该
修改父类
public String getInfo(String name) {
this.name=name;
return name;
}
修改主函数
System.out.println(b.getInfo(b.name));
System.out.println(s.getInfo(s.name));
这样你就可以用父类的方法,准确的把你要的值返回去。

[/Quote]
我快晕死过去了 人家楼主问的是他的代码的写法和他预期效果不一样的原因
不是问 怎么写就能得到他想要的
现在中国学程序的人 是不是语文都不好 哈哈
notlogin 2009-07-22
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 yq_love_rll 的回复:]
那如果要打印子类的name,该怎么办?
[/Quote]
你原来的代码已经很好的说明了getinfo getName的返回值为什么不同
notlogin 2009-07-22
  • 打赏
  • 举报
回复
我明白你的意思,按照你的想法 应该
修改父类
public String getInfo(String name) {
this.name=name;
return name;
}
修改主函数
System.out.println(b.getInfo(b.name));
System.out.println(s.getInfo(s.name));
这样你就可以用父类的方法,准确的把你要的值返回去。
lovecj6185 2009-07-22
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 yq_love_rll 的回复:]
谢谢18楼,我也是这么想的,因为我是初学者,不敢肯定···
[/Quote]

其实偶也是初学者,当不敢确定的时候,偶就去敲代码做试验拉
加载更多回复(19)

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧