美文网首页
类型转换与多态

类型转换与多态

作者: SingleDiego | 来源:发表于2018-03-16 15:35 被阅读6次

类型检查

Java 的任意变量和引用经过 类型声明(type declaration),才能使用。我们之前见过对象数据、类数据、方法参数、方法返回值以及方法内部的自动变量,它们都需要声明其类型。

Java是一种 强类型(strongly typing)语言,它会对类型进行检查。如果我们错误的使用类型,将造成错误。

比如在下面的 Test 类中,我们将一个 Cup 类对象赋予给 aPerson 类引用:

class Human
{   
    public Human(int h)
    {
        this.height = h;
    }

    public int getHeight()
    {
       return this.height;
    }

    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;
}


public class Test
{
    public static void main(String[] args)
    {
        Human aPerson;            
        aPerson = new Cup();     
    }
}

这将出现报错信息:

java:43: 错误: 不兼容的类型: Cup无法转换为Human
        aPerson = new Cup();
                  ^
1 个错误




基本类型转换

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

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

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

输出结果:

1

如果我们从低精度类型转换成高精度类型,则不存在信息损失的顾虑。这样的变换叫做 宽松变换(widening conversion)。我们不需要显示的要求类型转换,Java 可以自动进行:

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

输出结果:

3
基本类型转换




upcast 与多态

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

我们可以将一个衍生类引用转换为其基类引用,这叫做 向上转换(upcast)或者 宽松转换

下面的 BrokenCup 类继承自 Cup 类,并覆盖了 Cup 类中原有的 addWater()drinkWater() 方法:

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");
    }
}


public class Test
{
    public static void main(String[] args)
    { 
        Cup aCup;
        BrokenCup aBrokenCup = new BrokenCup();
        aCup = aBrokenCup; // 向上转换
        aCup.addWater(10); 
    }
}

输出结果:

shit, broken cup

在上面可以看到,不需要任何显示说明,我们将衍生类引用 aBrokenCup 赋予给它的基类引用 aCup。类型转换将由 Java 自动进行。

我们随后调用了 aCup (我们声明它为 Cup 类型)的 addWater() 方法。尽管 aCupCup 类型的引用,它实际上调用的是 BrokenCupaddWater() 方法!

也就是说,即使我们经过 upcast,将引用的类型宽松为其基类,Java 依然能正确的识别对象本身的类型,并调用正确的方法。Java 可以根据当前状况,识别对象的真实类型,这叫做 多态(polymorphism)。多态是面向对象的一个重要方面。

多态是 Java 的支持的一种机制,同时也是面向对象的一个重要概念。这提出了一个分类学的问题,既 子类对象实际上是父类对象。比如一只鸟,也是一个动物;一辆汽车,也必然是一个交通工具。Java 告诉我们,一个衍生类对象可以当做一个基类对象使用,而 Java 会正确的处理这种情况。

比如下面的继承关系:

我们可以说用杯子(Cup)喝水(drinkWater)。实际上,喝水这个动作具体含义会在衍生类中发生很大变换。比如用吸管喝水,和从一个破杯子喝水,这两个动作差别会很大,虽然我们抽象中都讲“喝水”。

我们当然可以针对每个衍生类分别编程,调用不同的 drinkWater 方法。然而,作为程序员,我们可以对杯子编程,调用 CupdrinkWater() 方法,而无论这个杯子是什么样的衍生类杯子。Java 会调用相应的正确方法,正如我们在上面程序中看到的。

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

class Human 
{
    void drink(Cup aCup, int w)
    {
        aCup.drinkWater(w);
    }
}


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

输出结果:

om...num..., no water inside

我们在 Human 类的 drink() 的定义中,要求第一个参数为 Cup类型的引用。但在实际运用时(Test类),该参数是 CupBrokenCup 衍生类对象。

这实际上是将 hisCup 向上转型称为 Cup 类,传递给 drink() 方法。在方法中,我们调用了 drinkWater() 方法。Java 发现这个对象实际上是 BrokenCup 对象,所以实际调用了 BrokenCup 的相应方法。




downcast

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




Object 类型

Java 中,所有的类实际上都有一个共同的继承祖先,即 Object 类。Object 类提供了一些方法,比如 toString()。我们可以在自己的类定义中覆盖这些方法。

相关文章

  • 类型转换与多态

    类型检查 Java 的任意变量和引用经过 类型声明(type declaration),才能使用。我们之前见过对象...

  • Kotlin继承与多态 (2)多态、is、as

    多态概念使用 is 和 !is 进行类型检查使用 as 和 as? 进行类型转换 一、多态概念 发生多态要有三个前...

  • C++类型强制转换

    类型转换 隐式类型转换 显式类型转换 语法 1. static_cast 用法用于非多态类型之间的转换,不提供运行...

  • java基础(5)

    多态详解 一共有两种类型的强制类型转换: (1)向上类型转换(upcast):比如说将cat类型转换为Animal...

  • c++语法3

    接上篇继续学习多态、类型转换 多态: 多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言...

  • 《Oracle Java SE编程指南》17-06:多态环境下对

    内容导航: 前言 1、类型转换 2、向上造型 3、向下造型 1、类型转换 当存在多态环境时,有时候需要类型转换。这...

  • c++类型转换

    一.静态类型转换 使用static_cast关键字,适用于普通类型转换&多态(父子类型转换,不需要实现virtua...

  • 2018-01-29

    c++类型转换 去const属性用const_cast。 基本类型转换用static_cast。 多态类之间的类型...

  • 多态和类型转换

  • Java继承与多态

    子类与父类、子类的继承性成员变量的隐藏与方法重写super与final关键字对象类型转换继承与多态抽象方法与抽象类...

网友评论

      本文标题:类型转换与多态

      本文链接:https://www.haomeiwen.com/subject/blulqftx.html