zoukankan      html  css  js  c++  java
  • Java基础12 类型转换与多态

    Java基础12 类型转换与多态

    我们之前使用类创造新的类型(type),并使用继承来便利我们创建类的过程。

    我将在这一讲中深入类型。并介绍多态(polymorphism)的概念。

     出处:http://www.cnblogs.com/vamei

    类型检查

    Java的随意变量和引用经过类型声明(type declaration),才干使用。

    我们之前见过对象数据、类数据、方法參数、方法返回值以及方法内部的自己主动变量。它们都须要声明其类型。Java是一种强类型(strongly typing)语言,它会对类型进行检查。假设我们错误的使用类型,将造成错误。


    类型不符,卖萌无效

     

    比方在以下的Test类中。我们将一个Cup类对象赋予给aPerson类引用:

    public class Test
    {
        public static void main(String[] args)
        {
            Human aPerson;            
            aPerson = new Cup();     
        }
    }
    
    class Human
    {   
        /**
         * constructor
         */
        public Human(int h)
        {
            this.height = h;
        }
    
        /**
         * accessor
         */
        public int getHeight()
        {
           return this.height;
        }
    
        /**
         * mutator
         */
        public void growHeight(int h)
        {
            this.height = this.height + h;
        }
    
        private int height;
    }
    
    class Cup 
    {
        public void addWater(int w) 
        {
            this.water = this.water + w;
        }
    
        public void drinkWater(int w)
        {
            this.water = this.water - w;
        }
    
        private int water = 0;
    }

    javac将返回:

    found   : Cup
    required: Human
                    aPerson = new Cup();             
                              ^
    1 error

     

    基本类型转换

    Java能够对基本类型的变量进行类型转换。不同的基本类型有不同的长度和存储范围。

    假设我们从一个高精度类型转换到低精度类型,比方从float转换到int。那么我们有可能会损失信息。这种转换叫做收缩变换(narrowing conversion)。这种情况下,我们须要显示的声明类型转换。比方:

    public class Test
    {
        public static void main(String[] args)
        {
            int a;
            a = (int) 1.23;  // narrowing conversion
            System.out.println(a);
        }
    }


    假设我们从低精度类型转换成高精度类型。则不存在信息损失的顾虑。

    这种变换叫做宽松变换(widening conversion)。我们不须要显示的要求类型转换。Java能够自己主动进行:

    public class Test
    {
        public static void main(String[] args)
        { 
            int a = 3;
            double b;
            b = a;  // widening conversion
            System.out.println(a);
        }
    }


    upcast与多态

    在Java中,引用也能够进行类型转换,可是有限制。


    我们能够将一个衍生类引用转换为其基类引用,这叫做向上转换(upcast)或者宽松转换。以下的BrokenCup类继承自Cup类,并覆盖了Cup类中原有的addWater()和drinkWater()方法:

    public class Test
    {
        public static void main(String[] args)
        { 
            Cup aCup;
            BrokenCup aBrokenCup = new BrokenCup();
            aCup = aBrokenCup; // upcast
            aCup.addWater(10); // method binding
        }
    }
    
    class Cup 
    {
        public void addWater(int w) 
        {
            this.water = this.water + w;
        }
    
        public void drinkWater(int w)
        {
            this.water = this.water - w;
        }
    
        private int water = 0;
    }
    
    class BrokenCup extends Cup
    {
        public void addWater(int w) 
        {
            System.out.println("shit, broken cup");
        }
    
        public void drinkWater(int w)
        {
            System.out.println("om...num..., no water inside");
        }
    }

    程序执行结果:

    shit, broken cup

     

    在上面能够看到,不须要不论什么显示说明,我们将衍生类引用aBrokenCup赋予给它的基类引用aCup。类型转换将由Java自己主动进行。

    我们随后调用了aCup(我们声明它为Cup类型)的addWater()方法。虽然aCup是Cup类型的引用,它实际上调用的是BrokenCup的addWater()方法!也就是说,即使我们经过upcast,将引用的类型宽松为其基类,Java依旧能正确的识别对象本身的类型,并调用正确的方法。

    Java能够依据当前状况,识别对象的真实类型,这叫做多态(polymorphism)。

    多态是面向对象的一个重要方面。

     

    多态是Java的支持的一种机制,同一时候也是面向对象的一个重要概念。

    这提出了一个分类学的问题。既子类对象实际上“是”父类对象。比方一仅仅鸟,也是一个动物;一辆汽车。也必定是一个交通工具。

    Java告诉我们。一个衍生类对象能够当做一个基类对象使用,而Java会正确的处理这样的情况。

    比方以下的继承关系:



    我们能够说用杯子(Cup)喝水(drinkWater)。实际上,喝水这个动作详细含义会在衍生类中发生非常大变换。比方用吸管喝水,和从一个破杯子喝水,这两个动作区别会非常大,尽管我们抽象中都讲“喝水”。我们当然能够针对每一个衍生类分别编程。调用不同的drinkWater方法。然而。作为程序猿,我们能够对杯子编程。调用Cup的drinkWater()方法。而不管这个杯子是什么样的衍生类杯子。Java会调用对应的正确方法。正如我们在上面程序中看到的。

    看一个更加有意义的样例。我们给Human类添加一个drink()方法,这种方法接收一个杯子对象和一个整数作为參数。整数表示喝水的水量:

    public class Test
    {
        public static void main(String[] args)
        {
            Human guest = new Human();
            BrokenCup hisCup  = new BrokenCup();
            guest.drink(hisCup, 10);
        }
    }
    
    class Human 
    {
        void drink(Cup aCup, int w)
        {
            aCup.drinkWater(w);
        }
    }

    程序执行结果:

    shit, no water inside

     

    我们在Human类的drink()的定义中。要求第一个參量为Cup类型的引用。但在实际运用时(Test类)。将Cup的BrokenCup衍生类对象。这实际上是将hisCup向上转型称为Cup类,传递给drink()方法。在方法中,我们调用了drinkWater()方法。Java发现这个对象实际上是BrokenCup对象,所以实际调用了BrokenCup的对应方法。

     

    downcast

    我们能够将一个基类引用向下转型(downcast)成为衍生类的引用,但要求该基类引用所指向的对象,已经是所要downcast的衍生类对象。比方能够将上面的hisCup向上转型为Cup类引用后。再向下转型成为BrokenCup类引用。

     

    Object类型

    Java中。全部的类实际上都有一个共同的继承祖先,即Object类。Object类提供了一些方法,比方toString()。

    我们能够在自己的类定义中覆盖这些方法。



                   Object: 祖先

     

    我们能够编写一个操作Object对象的程序,就能够通过upcast,将随意对象传递给该程序。

    我将在以后深入Object类。

     

    (多态的实现是依靠RTTI的支持。我将在以后深入。)

     

    总结

    基本类型转换

    polymorphism

    downcast

    Object


  • 相关阅读:
    leetcode 437. 路径总和 III
    leetcode 113. 路径总和 II
    题解 【CF387B】George and Round
    题解 【CF489B】 BerSU Ball
    题解【2.23考试T3】val
    题解【2.23考试T1】div
    题解 【洛谷P4290】 [HAOI2008]玩具取名
    题解 【洛谷P1035】[NOIP2002]级数求和
    题解【洛谷P1046】[NOIP2005] 陶陶摘苹果
    题解【洛谷P1618】 三连击(升级版)
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7353733.html
Copyright © 2011-2022 走看看