黑马程序员技术交流社区

标题: 面向对象 [打印本页]

作者: 郝林杰    时间: 2014-4-4 23:01
标题: 面向对象
class Foo{
ppublic int a;
public Foo(){
a=3;
}

public void addFive(){
a+=5;
}
}

class Bar extends Foo{
public int a;
public Bar(){
a=8;
}
public void addFive(){
this.a+=5;
}
}

public class TestFoo{
public static void main(String [] args){
   Foo foo=new Bar();
   foo.addFive();
System.out.prinfln(foo.a);
}
}

输出的结果我认为是:13 可是正确的结果并不是,why?
作者: 残梦共飞雪    时间: 2014-4-5 02:07
本帖最后由 残梦共飞雪 于 2014-4-5 10:15 编辑

原因是你子类Bar里面又定义了字段a,
Bar里的public int a;并未复写父类Foo的public int a;
也即构造时,有两个a,这两个a是不同的。主方法改成如下这般,可以直观显示:
public static void main(String[] args) {
                Foo foo = new Bar();
                System.out.println(foo.a);
                foo.addFive();
                System.out.println(foo.a);
                Bar bar = (Bar)foo;
                System.out.println(bar.a);
        }


结果为:
3
3
13


修改后的代码:
  1. class Foo {
  2.         public int a;

  3.         public Foo() {
  4.                 a = 3;
  5.         }

  6.         public void addFive() {
  7.                 a += 5;
  8.                 System.out.println("Foo a = " +a);
  9.         }

  10.         public int getA() {
  11.                 return a;
  12.         }
  13. }

  14. class Bar extends Foo {
  15.         public Bar() {
  16.                 a = 8;
  17.         }
  18.         @Override
  19.         public void addFive() {
  20.                 this.a += 5;
  21.                 System.out.println("Bar a = " +a);
  22.         }
  23. }

  24. public class TestFoo {
  25.         public static void main(String[] args) {
  26.                 Foo foo = new Bar();
  27.                 System.out.println(foo.a);
  28.                 foo.addFive();
  29.                 System.out.println(foo.a);
  30.         }
  31. }
复制代码

运行结果:8
Bar a = 13
13




作者: ノtrack    时间: 2014-4-5 08:59
首先,你那println写成ptinfln了,  你new Bar()时, 有条隐式的super(); 调用父类的构造函数,这是foo.a=3, 然后子类的a=8, 在复写父类的方法,调用子类的方法a+=5, 那么输出 bar a=13,  你foo.a则是调用是父类的a,, 所以成员变量不存在覆盖.      
作者: 759345779    时间: 2014-4-5 10:18
1.在多态中成员函数的特点:
        在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
        在运行时期:参阅对象所属的类中是否有调用的方法。
        简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
2.在多态中,成员变量的特点:
        无论编译和运行,都参考左边(引用型变量所属的类)。
3.在多态中,静态成员函数的特点:
        无论编译和运行,都参考做左边。

按照你的意思代码改成这样你看看:
  1. class Foo{
  2.         public int a;
  3.         public Foo(){
  4.                 a=3;
  5.         }

  6.         public void addFive(){
  7.                 a+=5;
  8.         }
  9. }

  10. class Bar extends Foo{
  11.         public int a;
  12.         public Bar(){
  13.                 super.a=8;
  14.         }
  15.         public void addFive(){
  16.                 super.a+=5;
  17.         }
  18. }

  19. public class TestFoo{
  20. public static void main(String [] args){
  21.         Foo foo=new Bar();
  22.         foo.addFive();
  23.         System.out.println(foo.a);
  24. }
  25. }
复制代码

作者: 山治0712    时间: 2014-4-5 14:17
成员变量编译运行都左边,知道吗,成员函数编译看左边运行看右边,希望对你有记忆




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2