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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 郭阳 中级黑马   /  2012-9-5 21:09  /  2158 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Animal是父类,Dog是子类。定义一个函数static void doSome(Animal a){}  他的传入值类型是Animal
新建一个对象Dog g=new Dog();   对象的类型是Dog
这个时候将g传入函数照样可以编译运行。这就可以说,子类都可以被看作是父类的类型吗?
问题在于毕老师视频中的 Animal g=new Dog();还有什么意义?
  1. public class Demo
  2. {
  3. public static void main(String[] args)
  4. {
  5. Dog d=new Dog();//创建的是Dog类型
  6. Guest.doSome(d);//但函数定义的传入类型是Animal,问题如上
  7. }
  8. }


  9. abstract class Animal
  10. {
  11. abstract void eat();
  12. void sleep()
  13. {
  14. System.out.println("睡觉");
  15. }
  16. }


  17. class Guest
  18. {
  19. static void doSome(Animal a)
  20. {
  21. a.eat();
  22. a.sleep();
  23. }
  24. }

  25. class Cat extends Animal
  26. {
  27. void eat()
  28. {
  29. System.out.println("吃鱼");
  30. }
  31. }


复制代码

评分

参与人数 1技术分 +1 收起 理由
王德升 + 1 赞一个!

查看全部评分

10 个回复

倒序浏览
只要子类继承了父类,子类对象都可以向上转型成父类的对象。至于你说的Animal g = new Dog()是父类的引用指向子类对象实现了多态。当想操作大量子类共有的方法是为了更简洁,更容易操作大量子类共有的方法时,Animal g = new Dog()就显得尤为的重要,Animal g这个动物引用类型可以接收所有子类动物。就相当于你想叫一大班人来吃饭,如果你一个一个的叫名字的话就会浪费很多的时间而且没有必有,你可以直接叫“吃饭了”他们都可以接收到这句话,执行吃饭的动作这样就节省了大浪的时间,又很简单。以你这个例子讲讲多态的主要特点和前提吧:
多态:可以理解为事物存在的多种体现形态

例如:
猫 x = new 猫();
动物 x = new 猫();

多态在程序中的体现:
   父类或者接口的引用指向了自己的子类对象。



多态是体现在对象上的。(对象的多态性)

1、多态的体现
   父类或者接口的引用指向了自己的子类对象。
2、多态的前提
   1,类之间必须存在关系(继承,实现)
   2,要有覆盖操作。
3、多态的好处
    提高了程序的扩展性。一种类型可以接受多种类型的具体对象
        比如动物类型可以接受其不同的子类对象。可以对事物的共性类型进行统一操作,将复杂问题简单化
       多态弊端
               一旦父类引用指向了自己的子类对象,那么父类引用在调用时,
                   只能调用父类中的方法。不能调用子类特有的方法。
4、多态的应用


*/


abstract class Animal
{
        abstract void eat();
}
class Dog extends Animal
{
        public void eat()
        {
                System.out.println("骨头");

        }
        public void lookHome()
        {
                System.out.println("看门");
        }
}
class Cat extends Animal
{
        public void eat()
        {
                System.out.println("老鼠");
        }
        public void ZhuaLaoShu()
        {
                System.out.println("抓老鼠");
        }
}
class DuoTaiDemo
{
        public static void main(String[] args)
        {
                /*Dog d = new Dog();
                d.eat();
                d.lookHome();
                Cat c = new Cat();
                c.eat();
                c.ZhuanLaoShu();
       */
           Animal a = new Dog();//多态   父类的引用指向子类对象,子类对象就被提升为了父类型。
           method(a);      //这种提升的好处,就是使用父类型对子对象进行操作,提高扩展性
                           //但是不能使用子对象的特有功能。
           Animal b = new Cat();
           method(b);
           /*
           如果要用到子类对象的特有方法时,可以对对象的类型进行强制类型的转换
           转型指定的对象的类型就可以使用对象的特有方法了
           如:Animal a = new Dog();(向上转型)
               Dog d = (Dog)a;(向下强制转型)
                 转型原则:自始至终其实都是子类对象在做着类型的变化。
           */

        }
        public static void method(Animal a/*传进来的形式参数是Animal类型的,Dog和Cat都是Animal类型的,这里用了多态*/)
        {
                a.eat();
                /*
                对具体的对象进行判断,需要使用一个关键字来完成。
                关键字就是:instanceof,
                */
                if (a instanceof Dog)
                {
                        Dog d = (Dog)a;
                        d.lookHome
                }
                else if (a instanceof Cat)
                {
                        Cat c = (Cat)a;
                        c.ZhuaLaoShu();
                }
        }
}

评分

参与人数 1技术分 +1 收起 理由
王德升 + 1 赞一个!

查看全部评分

回复 使用道具 举报
作为Animal 的子类Dog继承了其方法和属性,而方法中的参数不仅可以使基本数据类型还可以是类类型
回复 使用道具 举报
Animal是父类,Dog是子类。也即Dog继承了Animal类,定义一个函数static void doSome(Animal a){}  
这个方法参数列表是Animal,就是说只要是Animal类型的参数都能够接收,由于父类是向上抽取共同
之处得到的,所以Dog当然属于Animal类了,所以Dog传进去可以通过。
再有,新建一个对象Animal g=new Dog(); 虽然创建的是Dog,但是对象的类型是Animal,Animal有的
功能Dog都有,所以当用g来调用Animal的功能时完全可以,但是Dog除了有Animal的功能外,还有自己
特有的功能,这是要调用这些功能的话就要强转成Dog类型的。所以这个并不冲突!
回复 使用道具 举报
这就可以说,子类都可以被看作是父类的类型吗?
问题在于毕老师视频中的 Animal g=new Dog();还有什么意义?
--------------------------------------------------------------
第一个问题,子类都可以看做是父类的类型吗?
不能这么理解,子类继承父类,在继承父类的类属性和类方法的同时,还可以创建自己的属性和方法!继承的目的就是对父类的一些属性和功能的扩充,他们谈不上子类是父类的对象类型,也不应该这么理解!
第二个问题: Animal g=new Dog()意义,这里是dog是子类,Animal是父类,发生了向上类型的转换!
回复 使用道具 举报
武庆东 发表于 2012-9-5 21:44
这就可以说,子类都可以被看作是父类的类型吗?
问题在于毕老师视频中的 Animal g=new Dog();还有什么意义 ...


谢谢大家的回答。我知道是发生了类型提升向上转换。。。我的问题是他为什么要这么做。。。
为了可以把该对象传到接受值为Animal的函数里?那没有必要啊,用dog类型就可以啊。而且用animal的话,如果函数需要调用dog类型的方法,还要再强制向下转型。。。多麻烦。。。
还是毕老师就是为了讲 类型转换?
回复 使用道具 举报
本帖最后由 杨习平 于 2012-9-5 22:25 编辑

(1)子父类中的成员关系
                A:成员变量
                        在子类方法中使用一个变量时:
                        首先,在方法的局部变量中找这个变量,有则使用。
                        否则,在本类中找成员变量,有则使用。
                        否则,在父类中找成员变量,有则使用。
                        否则,报错。
                B:成员方法
                        用子类对象使用一个方法时。
                        首先,在子类中找这个方法,有则使用。
                        否则,在父类中找这个方法,有则使用。
                        否则,报错。

                        当子父类中的方法名相同时的现象被称为重写。

                       C:构造方法
                        **子类的实例化过程
                                ***子类创建对象时,会先去创建父类的对象。
                                    默认是去调用父类的无参构造方法。
                                ***子类构造方法中,第一行默认是super()
                                ***为什么子类中第一行会默认有super()
                                        因为他继承父类的成员使用,使用前这些成员必须初始化,
                                        而他们是父类的成员,所以,必须通过父类进行初始化。
                                        所以,会先创建一个父类的对象。
                        **当父类没有无参构造方法时
                                必须使用this或者super调用其他的构造方法。
        (2)this和super的区别
                this:代表本类对象的引用。
                super:代表父类的存储空间。
          (3)继承的代码体现如下。
   你的问题涉及到了多态,下面这个例子你会明白的。
  /*
多态中用多态对象访问成员时的特点:
成员变量:
        编译看左边,执行看左边。
成员方法:
        编译看左边,执行看右边。
静态方法:
        编译看左边,执行看左边。        
*/
abstract class Fu
{
        int num = 10;

        void show()
        {
                System.out.println("fu-show");
        }

        static void method()
        {
                System.out.println("Fu-method");
        }
}

class Zi extends Fu
{
        int num = 20;
        int num2 = 30;

        void show()
        {
                System.out.println("zi-show");
        }

        void show2()
        {
                System.out.println("zi-show2");
        }

        static void method()
        {
                System.out.println("zi-method");
        }
}

class DuoTaiDemo4
{
        public static void main(String[] args)
        {
                Fu f = new Zi();//向上转型,多态
                System.out.println(f.num);

                f.show();
                f.method();
        }
}
你在23.static void doSome(Animal a)这里面传的是一个类,而这个类是Dog的父类,只要是他有的属性,父类都有,你说的子类能不能看成是父类,这个问题多的关键是他继承了Animal,所以才能编译通过。所以多想想,就清楚了。
回复 使用道具 举报
郭阳 发表于 2012-9-5 22:22
谢谢大家的回答。我知道是发生了类型提升向上转换。。。我的问题是他为什么要这么做。。。
为了可以把该 ...

当然不是,如果你了解为什么用向上转型的作用,你就不会这样问了!
回复 使用道具 举报
武庆东 发表于 2012-9-6 12:53
当然不是,如果你了解为什么用向上转型的作用,你就不会这样问了!

就是因为不了解为什么用向上转型,
就所以才开的这个帖子提问.....
从一开始就是这个问题......:L
回复 使用道具 举报
郭阳 发表于 2012-9-6 14:47
就是因为不了解为什么用向上转型,
就所以才开的这个帖子提问.....
从一开始就是这个问题...... ...

咳咳,楼主问的这个问题我可以理解成问:为什么要抽象?

我热爱java的主要原因是java的高可扩展性,举一个例子~

比如,你要一个充气娃娃,这个充气娃娃有一个makeLove方法,你买这个娃娃就是冲着makeLove去的,你不关心它是哪国的娃娃,长得怎样。那么代码就体现为:

interface Chongqiwawa{
public void makeLove(String name);
}

class Person{
Chongqiwawa wawa;
public void setWawa(Chongqiwawa wawa){
  this.wawa = wawa;
}
private String name;
public void makeLove(){
  //调用wawa的makeLove方法
  wawa.makeLove(name);
}
现在,你想和wawa那个,就可以这样用了:
main(){
  Person you = new Person();
  you.makeLove();
}

报错了吧?你怎么能跟虚的wawa那个呢?所以必须要买一个wawa.好吧,去逛成人店选购一个wawa.这里有日本娃娃,美国娃娃,先看看美国娃娃功能怎么样。

class USAWawa implements Chongqiwawa{
  public void makeLove(String name){
  System.output.println(name + " come on! a,a, a...");  
  }
}
好吧,你已经流口水了,一口价成交,然后带回家,迫不及待实践一下,代码体现为:
main(){
  Person you = new Person();
  Chongqiwawa wawa = new USAWawa();
  you.setWawa(wawa);
  you.makeLove();
}

这时候你已经可以和娃娃水乳交融了。不久,你发觉厌倦了美国娃娃,想试下日本娃娃,再次来到成人超市,日本娃娃makeLove功能实现如下:
class JapanWawa implements Chongqiwawa{
  public void makeLove(String name){
  System.output.println(name + " yemede! a,a, a...ganbade...");  
  }
}
OK,你直接丢下一堆钞票一句不用找就抱回家了,马上进入主题:

main(){
  Person you = new Person();
  //获得实际的wawa
  Chongqiwawa wawa = new JapanWawa();
  you.setWawa(wawa);
  you.makeLove();
}
看见了吗,只需改动一行代码,你就实现了娃娃的切换,得到不同的makeLove感受,其他代码都不用改。
这就是接口!

结束语:java的“迟绑定特性”决定了可以在运行时才知道实际需要调用的方法,或者实际实例化的对象,这样为java多态提供了可能性
回复 使用道具 举报
yellowbaby 发表于 2012-9-6 15:44
咳咳,楼主问的这个问题我可以理解成问:为什么要抽象?

我热爱java的主要原因是java的高可扩展性,举一 ...

修改名字,
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马