A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张昊镭 黑马帝   /  2012-3-24 18:03  /  2327 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

在第八天讲多态的时候,有这样一段代码:
abstract class Animal
{
        public abstract void eat();
}
class Cat extends Animal
{
        public void eat()
        {
                System.out.println("eat fish");
        }
        public void catchMouse()
        {
                System.out.println("catch mouse");
        }
}
class Dog extends Animal
{
        public void eat()
        {
                System.out.println("eat bone");
        }
        public void watchHome()
        {
                System.out.println("watch home");
        }
}
class PolymorphismDemo
{
        public static void main(String[] args)
        {
                function(new Cat());
                function(new Dog());
        }
        public static void function(Animal a)
        {
                a.eat();
        }
}
我的问题:
1.倒数第三行的a.eat()这个a调用的eat()方法为什么是子类的方法,而不是父类的?
2.我百度了下,查到说是引用变量a有2个类型,编译的时候类型为Animal,运行的时候类型为子类,所以在代码编译过程中,a调用的是Animal的eat()方法, 在运行代码的时候调用的是子类的eat()方法,这就是多态,那么我的第一个问题应该这样解释吗?这个方法的调用顺序是java的特性吗?

9 个回复

倒序浏览
子类复写了父类的方法就会调用自己特有的方法
回复 使用道具 举报
function(Animal a)中的 a 是形式参数,只有运行的时候,谁调用他,给他传进来的具体是个什么对象,他才会调用这个对象中的重写后的方法。 这也是对态度的好处,如果不以Animal做参数,你要用猫时候 就要定义个 Cat a,用狗时候又要写个方法是用 Dog a做参数,要是有几百个动物 ,不累死了
回复 使用道具 举报
这是Java面向对象的一个特性:运行时多态。Animal a=new Cat();a.eat();在编译的时候会判断Animal类中有没有eat()方法,如果没有就会抛出异常。在运行时a本身是创建的Cat对象,而Cat类中已经重写(覆盖)了父类的方法,会调用Cat类的eat()方法,这就是运行时多态。
回复 使用道具 举报
说一个师兄教给我的通俗的例子吧,车都能跑,奥托是车的子类继承车的方法也可以跑,但跑的慢(覆写车跑的方法),奥迪车不仅继承车的行为会跑而且跑的快(覆写车跑的方法)还有自己特有的行为能泡到美眉。如果这时是奥迪对象调用跑的方法就跑的快,但是奥托对象调用跑的行为就跑的慢;如果这时有一个哥们明明开的是奥迪却只跟美眉说他有车没说是奥迪(Car c = new aodi())那么此时他就没有泡不到美眉。此时就需要强转一下才能调用泡美眉的行为。
回复 使用道具 举报
Animal是抽象类。抽象类不能产生对象的,但可以由它的实现类来声明对象。既然没有对象也就没有调用它的函数之说。再者父类中的eat(),也是抽象的,也不会运行的哦。。Cat Dog 都是Animal的实现类 。function(new Cat());
function(new Dog());
传进去的是子类对象,当然调用子类的eat()
寻找执行方法的原则是: 先在对象所属的类中寻找匹配的方法,没有再找父类,祖先类
回复 使用道具 举报
a是new Cat()对象和new Dot()对象的上转型对象。
如果子类重写了父类的某个方法后,当对象的上转型对象调用方法时一定是调用了子类重写的方法。
子类猫和狗类都重写了父类动物的eat()方法,a调用eat()方法时一定是调用子类重写的方法,即猫和狗的eat()方法。
回复 使用道具 举报
本帖最后由 邓飞飞 于 2012-3-24 19:28 编辑

class PolymorphismDemo
{
         public static void main(String[] args)
         {
                 function(new Cat());
                 function(new Dog());
         }
         public static void function(Animal a)
         {
                 a.eat();
         }
}
这段代码用啰嗦的方法写出来,这样看起来就会容易理解一些:
class PolymorphismDemo
{
         public static void main(String[] args)
         {
                 function(new Cat());                 //Cat m=new Cat();function(m);
                 function(new Dog());                //Dog d=new Dog();function(d);
         }
         public static void function(Animal a)   //调用时a=m,a=d
         {
                 a.eat();
         }
}
Animal类是对Cat类和Dog类更高级的抽象,它里面的方法体是不确定的,所以是抽象类。通过Cat类和Dog类实例化了,有了自己特有的方法体, 进而通过多态   (Animal a=new Cat()/new Dog()) 来调用自己自己本类的方法.还有调用父类的方法是没有意义的,因为它没有方法实体.
回复 使用道具 举报
岳民喜 黑马帝 2012-3-24 20:20:44
9#
其实这个是涉及 到多态的前提, 通常有一个前提:存在覆盖。  因为Animal类中的eat(),是抽象方法, 没有具体执行内容,必须调用子类的特有方法覆盖父类中的抽象方法。所以你调用父类的eat()目的,实际上是你想调用父类下面子类的方法。
回复 使用道具 举报
楼主说的好像挺对的。老师视频里面也是这样说的。复习了下
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马