子类重写属性,调用.people时为什么仍为父类属性?(课后练习问题)

来源:10-1 Java 中的多态

shanmufeng

2015-07-09 15:06

public class Traffic {
	public int people;
	public String location;
	@Override
	public String toString() {
		return "Traffic [people=" + people + ", location=" + location + "]";
	}
}

public class Bus extends Traffic {
	public int people = 40;            
	public String location = "陆地";               //重写属性
	@Override
	public String toString() {
		return "Bus [people=" + people + ", location=" + location + "]";
	}
}

public class Initial {
	public static void main(String[] args) {
		Traffic tra1 = new Bus();
		System.out.println(tra1);       //输出Bus [people=40, location=陆地]
		
		System.out.println(tra1.people);//输出0,为什么不是40?成员变量不能重载?
	}
}


写回答 关注

2回答

  • 无敌的大鹏鸟
    2015-07-27 18:12:37

    这么跟你解释,父类和子类中同名的两个属性是完全不同的两个属性,它们其实毫无关系,只是你定义得同名而已,所以也不存在什么属性重写的概念,它们只是对各自的属性初始化而已,即使你把他们赋相同的初值,它们也是两个完全不同的属性,从本质上他们的内存地址就不一样。

    System.out.println(tra1.people);你的这句话,是用父类的对象访问父类的属性people,由于你在父类中没有初始化,所以系统默认为0.  这是我的理解,希望能帮到你,最后记住,不存在属性的重写,他们根本没关系,只是同名而已。

  • donlv
    2015-07-09 17:38:32

    Java的多态性

    面向对象编程有三个特征,即封装、继承和多态。

       封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据。

       继承是为了重用父类代码,同时为实现多态性作准备。那么什么是多态呢?

       方法的重写、重载与动态连接构成多态性。Java之所以引入多态的概念,原因之一是它在类的继承问题上和C++不同,后者允许多继承,这确实给其带来的非常强大的功能,但是复杂的继承关系也给C++开发者带来了更大的麻烦,为了规避风险,Java只允许单继承,派生类与基类间有IS-A的关系(即“猫”is a “动物”)。这样做虽然保证了继承关系的简单明了,但是势必在功能上有很大的限制,所以,Java引入了多态性的概念以弥补这点的不足,此外,抽象类和接口也是解决单继承规定限制的重要手段。同时,多态也是面向对象编程的精髓所在。

       要理解多态性,首先要知道什么是“向上转型”。

       我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类。我可以通过

    Cat c = new Cat();
    实例化一个Cat的对象,这个不难理解。但当我这样定义时:

    Animal a = new Cat();
    这代表什么意思呢?

       很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特,

    定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。

    所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是无可奈何的;

    同时,父类中的一个方法只有在在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用;

    对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接。

    看下面这段程序:

    class Father{
       public void func1(){
           func2();
       }
       //这是父类中的func2()方法,因为下面的子类中重写了该方法
       //所以在父类类型的引用中调用时,这个方法将不再有效
       //取而代之的是将调用子类中重写的func2()方法
       public void func2(){
           System.out.println("AAA");
       }
    }
     
    class Child extends Father{
       //func1(int i)是对func1()方法的一个重载
       //由于在父类中没有定义这个方法,所以它不能被父类类型的引用调用
       //所以在下面的main方法中child.func1(68)是不对的
       public void func1(int i){
           System.out.println("BBB");
       }
       //func2()重写了父类Father中的func2()方法
       //如果父类类型的引用中调用了func2()方法,那么必然是子类中重写的这个方法
       public void func2(){
           System.out.println("CCC");
       }
    }
     
    public class PolymorphismTest {
       public static void main(String[] args) {
           Father child = new Child();
           child.func1();//打印结果将会是什么?    
       }
    }
       上面的程序是个很典型的多态的例子。子类Child继承了父类Father,并重载了父类的func1()方法,重写了父类的func2()方法。重载后的func1(int i)和func1()不再是同一个方法,由于父类中没有func1(int i),那么,父类类型的引用child就不能调用func1(int i)方法。而子类重写了func2()方法,那么父类类型的引用child在调用该方法时将会调用子类中重写的func2()。

       那么该程序将会打印出什么样的结果呢?

       很显然,应该是“CCC”。

       对于多态,可以总结它为:

    一、使用父类类型的引用指向子类的对象;

       二、该引用只能调用父类中定义的方法和变量;

       三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)

       四、变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错。

Java入门第二季 升级版

课程升级!以终为始告别枯燥,在开发和重构中体会Java面向对象编程的奥妙

530652 学习 · 6091 问题

查看课程

相似问题