My FAQ,最新最全的IT技术FAQ
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 未整理篇 | 技术讨论
  当前位置: > 程序开发 > 编程语言 > Java > 综合文章
关于类继承的问题.
作者:未知 时间:2005-09-13 19:40 出处:ChinaUnix.net 责编:My FAQ
              摘要:关于类继承的问题.

大家帮我看一下这段程序:
class Superclass
{
int x;
void setX()
{
x=10;
}
}

class Subclass extends Superclass
{
int x;     //隐藏了父类的成员变量x
/*void setX()//重写父类的方法setX()
{
x=5;
}*/
public static void main(String []args)
{
Subclass sub=new Subclass();
System.out.println(sub.x);
sub.setX();
System.out.println(sub.x);
}
}

这个程序执行的结果怎么是0,0啊
我认为是0,10

请问高手,这种程序的如何执行的啊?

 sakulagi 回复于:2005-06-17 08:11:15
【1】 Field和method不一样,没有overriding,只有hiding。Field是按声明类型(或者叫引用类型),而不是实际类型来解析的。比如你的例子里,如果改成
[code:1:83b2b1ff3e]
Superclass sub = new Superclass();
[/code:1:83b2b1ff3e]
那么sub.x会指向Superclass里的x,即使sub的实际类型是Subclass。

【2】在对Superclass.setX()里边的x作解析的时候,会解析城这样:
[code:1:83b2b1ff3e]
((Superclass)this).x
[/code:1:83b2b1ff3e]
而根据【1】,这个x在任何情况下都被指向了Superclass.x,所以调用setX()永远无法给Subclass.x赋值。

 cooljia 回复于:2005-06-17 20:20:25
艾, 搞过一段时间sjcp, 所以对此类的题目还是有点印象.      
Superclass sub1 = new Subclass();
Superclass super = new Superclass();

sub1.x和super.x在Subclass中的main方法中是指向的都是父类中的x

只有
Subclass sub2 = new Subclass();
sub2.x才是子类中的x.

 leonbao 回复于:2005-06-27 18:04:22
我认为以上两位并没有完全准确回答楼主的问题。
我认为,原则上父类是看不到子类的方法和属性的,因此在父类里也就不能去调用子类里的方法或改变子类里的属性。
但在子类里可以调用父类的方法或改变父类的属性。不过要分两种情况:
1. 如果在父类里的某一个方法或属性在子类内没有重新定义,那么在子类里可以直接调用父类里的这个方法或者改变这个属性。
class Superclass
{
int x;
void setX()
{
x=10;
}
}

class Subclass extends Superclass

 void aMethod()
{
x=20; // 改变 SuperClass 里的 x
setX(); // 调用 SuperClass 里的 setX()
}
}

2. 如果在父类里的某一个方法或属性在子类内被重新定义,那么在子类里直接调用或者改变的是在子类里新定义方法或者属性。如想调用父类里被覆盖的方法或改变父类里被覆盖的属性,则必须加super前缀。
class Superclass
{
int x;
void setX()
{
x=10;
}
}

class Subclass extends Superclass

int x;
void setX()
{
x=30;
}

 void aMethod()
{
x=20; // 改变 SubClass 里的 x
setX(); // 调用 SubClass 里的 setX()
super.x=20; // 改变 SuperClass 里的 x
super.setX(); // 调用 SuperClass 里的 setX()
}

}


在楼主的程序里,SubClass 里的setX() 被注释掉了,因此在运行时是父类的setX()被调用了,而父类的方法只能改变父类里的属性。也就是说父类里的x的值变为10,而子类里的x还是0。main() 里的sub.x 得到的一直是子类里的x的值。

 sakulagi 回复于:2005-06-27 22:16:40
父类自然是看不见子类的任何内容,因为父类不知道有子类的存在。

但是,对于一个实例来说,它既是父类的实例,也是子类的实例。而一个名字是在运行时解析的,那么这个时候x是指父类里的x,还是子类的x呢?如果把Superclass的setX方法写成
[code:1:a9a7145694]
void setX()
{
    this.x=10;

[/code:1:a9a7145694]
那么在调用sub.setX()的时候,this.x指的是父类还是子类的实例呢?这个this.x是父类的x还是子类的x?

所以探讨一下名字解析的规则还是有意义的。

另外,如果子类定义了和父类相同签名的方法,那么在父类里调用的将是子类的方法。这个是Java的最基本的特性了。所以不能笼统的说“父类不能访问子类的方法和属性”。方法和属性的访问规则是不一样的。

 tangchaodong 回复于:2005-06-28 14:06:29
int x;     //隐藏了父类的成员变量x 
把该句隐掉就得到了0,10

 rabbit008 回复于:2005-06-29 10:59:49
1. //Test.java
public class Test extends Super2{
    int x=2;

    void setx(int value){
        x = value;
    }
    int getsuperx(){
        return super.x;
    }
    public static void main(String[] args)
    {
        try{
            Test t = new Test();
            System.out.println(t.x);//2
            t.setx(10);
            System.out.println(t.getX());//0
            System.out.println(t.getsuperx());//1
            System.out.println(t.x);//10
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

class Super1{
    int x=0;

    void setx(int value){
        x = value;
    }
}

class Super2 extends Super1{
    int x=1;

    void setx(int value){
        x = value;
    }
    int getX(){
        return super.x;
    }
}




2.  //Test.java
public class Test extends Super2{
    int x=2;

  /*void setx(int value){
        x = value;
    }*/
    int getsuperx(){
        return super.x;
    }
    public static void main(String[] args)
    {
        try{
            Test t = new Test();
            System.out.println(t.x);//2
            t.setx(10);
            System.out.println(t.getX());//0
            System.out.println(t.getsuperx());//10
            System.out.println(t.x);//2
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

class Super1{
    int x=0;

    void setx(int value){
        x = value;
    }
}

class Super2 extends Super1{
    int x=1;

    void setx(int value){
        x = value;
    }
    int getX(){
        return super.x;
    }
}



3. //Test.java
public class Test extends Super2{
   /* int x=2;

  void setx(int value){
        x = value;
    }*/
    int getsuperx(){
        return super.x;
    }
    public static void main(String[] args)
    {
        try{
            Test t = new Test();
            System.out.println(t.x);//1
            t.setx(10);
            System.out.println(t.getX());//0
            System.out.println(t.getsuperx());//10
            System.out.println(t.x);//10
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

class Super1{
    int x=0;

    void setx(int value){
        x = value;
    }
}

class Super2 extends Super1{
    int x=1;

    void setx(int value){
        x = value;
    }
    int getX(){
        return super.x;
    }
}


写了程序测试了一下,好像有点明白了:)。
当子类调用一个方法时,它会一层一层的向上找,也就是先再自己的类中找,然后到父类中找,以此类推,直到找到为止,而这个方法要赋值的字段,只会改变本类和祖先类的字段,而不会改变子类的字段。
当子类使用一个字段时,也是同样的原则,它会一层一层的向上找,也就是先再自己的类中找,然后到父类中找,以此类推,直到找到为止。
看看例子了。
第一个例子,子类中有字段x , 和 setx() 方法, 所以调用 的字段,方法都是它本身的,在调用setx() 之前,字段 x 是 2 (而不是 1 或 0), 调用了 setx(10) 后(相当于改变了自己类中的字段x的值),得到的 x 为10 ,super.x 为1, super.super.x 为 0。
第二个例子,子类中有字段x , 但没有 setx() 方法, 所以调用 的字段是它本身的,而方法是其父类的,在调用setx() 之前,字段 x 是 2 (而不是 1 或 0), 调用了 setx(10) 后(由于自己的类中没有setx()方法,向上寻找,在父类中找到了setx(), 但是调用父类的方法只会改变父类的字段或父类的父类的字段,由于父类中有x这个字段,所以父类的字段x被改成了10),得到的 x 为2 ,super.x 为10, super.super.x 为 0。
第三个例子,子类中没有字段x , 也没有 setx() 方法, 所以调用 的字段和方法方法都是其父类的,在调用setx() 之前,字段 x 是 1 (不是 0,说明是父类的字段值), 调用了 setx(10) 后(由于自己的类中没有setx()方法,向上寻找,在父类中找到了setx(), 但是调用父类的方法只会改变父类的字段或父类的父类的字段,由于父类中有x这个字段,所以父类的字段x被改成了10),得到的 x 为10,super.x 为10, super.super.x 为 0。
您可以接着把父类中的 setx() 方法隐掉,保留x,看看会得到什么结果。
x=1, after setx(10), x = 1, super.x=1, super.super.x=10
把 父类中的 x 隐掉, 保留 setx(),
x=0, after setx(10), x = 10, super.x=10, super.super.x=10

 tangchaodong 回复于:2005-06-29 13:56:58
我也是这样想的,哈哈!
这算不算是java运行的机制?

 sakulagi 回复于:2005-06-29 18:49:54
这个可以查看Java Language Specification

 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 myfaq.com.cn All rights reserved. www.myfaq.com.cn 版权所有