黑马程序员技术交流社区

标题: 多态问题 [打印本页]

作者: 伊廷文    时间: 2013-3-27 21:55
标题: 多态问题
多态中,什么是向下转型和向上转型,能具体说一下多态吗
作者: itserious    时间: 2013-3-27 22:14
  1. package test;


  2. public class Test6 {
  3.        
  4.         public static void main(String[] args) {
  5.                 Person p=new Student();//这就是向上转型,父类引用指向子类对象。
  6.                 System.out.println(p);
  7.                
  8.                 Student s=(Student)p;//这就是向下转型。将父类强转成子类。
  9.                 s.show();
  10.         }
  11. }

  12. class Person{
  13.         String name="zzz";

  14.         @Override
  15.         public String toString() {
  16.                 return "Person [name=" + name + "]";
  17.         }
  18.        
  19. }
  20. class Student extends Person{
  21.         int age=20;
  22.         void show(){
  23.                 System.out.println("name="+name+",age="+age);
  24.         }
  25.         @Override
  26.         public String toString() {
  27.                 return "Student [age=" + age + "]";
  28.         }
  29.        
  30. }
复制代码

作者: 贾振凯    时间: 2013-3-27 22:35
  1. /**
  2. * 首先定义两个类A  和 A的子类B
  3. * 类的实例属性我写成了public是为了便于回答问题,不推荐哈!!
  4. */
  5. class A {
  6.        
  7.         public String a="A";
  8.        
  9.         public void method1(){
  10.                 System.out.println("A1");
  11.         }
  12. }
  13. class B extends A{
  14.        
  15.         public String a="B";
  16.        
  17.         public void method1(){
  18.                 System.out.println("B1");
  19.         }
  20.        
  21.         public void method2(){
  22.                 System.out.println("B2");
  23.         }
  24. }
  25. /**
  26. * 向上转型: A a = new B(); 把子类对象赋给了父类类型变量,这个转型时系统自动进行的,并且总是安全的
  27. * 向下转型: B b = a; 把父类类型变量赋给子类类型变量,这个属于强制转型,并且有一定风险
  28. *        为了确保安全,一般使用如下形式进行向下转型
  29. *        if(a instance B){
  30. *                B bb = (B)a;
  31. *        }
  32. * 上面的两种转型体现的就是多态:
  33. * 在多太中有两个注意点:
  34. * 1.方法:看运行时类型,即new的谁就执行谁的方法,
  35. *       可执行的方法要看编译时类型,即编译的类里面有什么方法该变量才可以运行什么方法
  36. *       像上边a变量就只能调用method1()方法,而且输出的是"B1"
  37. * 2.属性:只看编译时类型
  38. *       像上边a.a的值就是"A"
  39. */
复制代码

作者: 聂斌    时间: 2013-3-27 23:49

(1),,,向上转型,,向下转型

向上转型 :
                Animal a = new Cat();//类型提升。这个类型提升我们也称为 向上转型。这个提升动作是自动完成的,把猫就提升为了动物,,这个a引用可以作为动物的引用也可以把a强转成猫
                a.eat();


类型提升比如:  byte a=2;  int b=a; a会被提升为int类型 ,,这也是向上转型

向下转型:
                //如果想要调用猫的特有方法时,如何操作?
                           那么就得强制将父类的引用。转成子类类型。向下转型。
                        Cat c = (Cat)a;
                        c.catchMouse();
                //千万不要出现这样的操作,就是将父类对象转成子类类型。其实我们转的是父类的引用
                //我们能转换的是父类引用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换。
                //规律:多态自始至终都是子类对象在做着变化。这里猫一会变成动物,一会又变成猫




(2),,,错误的向下转型
                Animal a = new Animal();  假设父类可以创建对象的
                Cat c = (Cat)a;
这样不行,,因为你不能强制将一个动物转成猫,动物是先出现的,猫是后出现的,你把一个动物转成猫,那么动物这对象里面他不具备猫特有的方法,所以这个猫 c  是不可能调用抓老鼠的方法的,,a里面没有猫特有的方法,,你不能把以前有的东西强转换为现在的东西,,比如我要一只猫,,你给我猫是对的,但是你给我一动物,,那动物不确定是啥,他有可能是猪,,,
不能强制把 a 变成 Cat ,,,那个时候有可能还没有子类,怎么把父类变成子类呢,你就是真的有子类了,但是父类没有子类特有的功能

(3),多态中需要注意:

(a)
成员函数在多态调用时,编译看左边,运行看右边。

看代码

Fu f = new Zi();  f这个引用绑定在了ew Zi对象上
                f.method1();
                f.method2();
                f.method3();

你编译的时候看的是f这个引用型变量所属的类Fu他里面是不是有下面调用的方法.method1(),
运行的时候看的是new Zi()这个对象所属的类Zi类里面有没有f.method1();f.method2();,有就运行子类自己的方法method1();f.method2()


(b)

class Fu
{
        int num=5;
        void method1()
        {
                System.out.println("fu method_1");
        }
        void method2()
        {
                System.out.println("fu method_2");
        }

}


class Zi extends Fu
{

        int num=8;
        void method1()
        {
                System.out.println("zi method_1");
        }
        void method3()
        {
                System.out.println("zi method_3");
        }

       
}

public class JinJhi {

        /**
         * @param args
         */
        public static void main(String[] args) {
                Fu f = new Zi(); ,父类引用指向子类对象,这里走的还是父类的
                System.out.println(f.num);

                 Zi z = new Zi();
                System.out.println(z.num);

结果是: 4,5

在多态中,成员变量的特点:num都是静态成员变量的话,也是看左边
无论编译和运行,都参考左边(引用型变量所属的类)。参考父类

new Zi(); 这个对象建立的时候,堆内存里面一产生完以后,这个对象有2个变量,一个是父类的num一个是子类的num,,,你在拿父类的引用去找这num的时候,他会先找父类的num.他有自己的num,所以找自己的了,,当父类子类出现同名变量的时候,多态Fu f = new Zi()情况下看左边的Fu f


(c)

class Fu
{
        static int num = 5;
        void method1()
        {
                System.out.println("fu method_1");
        }
        void method2()
        {
                System.out.println("fu method_2");
        }
        static void method4()
        {
                System.out.println("fu method_4");
        }
}


class Zi extends Fu
{
        static int num = 8;
        void method1()
        {
                System.out.println("zi method_1");
        }
        void method3()
        {
                System.out.println("zi method_3");
        }

        static void method4()
        {
                System.out.println("zi method_4");
        }
}

Fu f = new Zi();
f.method4();

Zi z = new Zi();
z.method4(); 他看的是左边那个引用性变量所属类中的内容,静态先加载不属于对象,所以调用的是父类的静态内容

结果第一个打印的是父类的方法,第二个打印的是子类的静态方法

在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。
原因:method4()静态方法当你在调用的时候,建立子类对象的话,这个时候父类和子类都会加载进内存,一进内存,发现静态内容先存在了这时不需要对象,直接可以Fu .method4(); Zi.method4();

静态就是只参考那个引用所属的类,,f属于fu








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