SCJP认证 第二章 面向对象 2.3多态性

17 篇文章 0 订阅

目标

5.2 给定一个场景,编写代码,演示多态性的使用。而且,要判断何时需要强制转换,还要区分与对象引用 强制转换相关的编译器错误和运行时错误。

 

 记住可以传递多个IS-A测试的任何Java对象都可以被看作是多态的。除了Object类型的对象之外,其他所有Java对象都是多态的,这在于它们为自己的类型以及Object类传递IS-A测试。

记住,访问对象的唯一方式是通过引用变量。关于引用,要记住的几个要点如下:

  • 引用变量只能属于一种类型。一经声明,类型就永远不能再改变(尽管它引用的对象可以改变类型) 。
  • 引用是一个变量,因此它可以重新赋予其他对象(除非该引用被声明为final)
  • 引用变量的类型决定了可以在该变量引用的对象上调用的方法。
  • 引用变量可以引用具有与所声明引用的类型相同的任何对象,或者——最重要的一点是——它可以引用锁声明类型的任何子类型!
  • 引用变量可以声明为类类型或接口类型。入股瓯江变量声明为接口类型,它就可以应用事项该接口的任何类的任何对象。

 早先我们创建了被另外两个类PlayPiece和TilePiece扩展的GameShape,类现在假设你希望是某些形状在游戏板实现动画效果,但是并非所有形状都是可以运动的,那么可以利用类继承做什么呢?

是否可以创建一个带有animate()方法的类,并且只有某些GameShape子类是继承自该类的?

如果可以这样做,那么就能够具有PlayerPiece,它同时扩展了GameShape类和Animatable类,但是TilePiece将只会扩展GameShape。不过,这样做是不行的!Java值支持单一的继承!这意味着一个类只能有唯一的直接超类。换句话说,如果PlayPice是一个类,则不能这样编写代码:

 那么,存在别的方法吗?你已经知道了答案了——创建一个Animatable接口,并且只让那些可以实现动画效果的GameShape紫了实现该接口。该接口的代码如下:

 以下是实现该接口的修改过的PlayerPiece类:

因此,现在我们就有了以个PlayerPiece,它同时为GameShape类和Aniamtable接口传递IS-A测试。这意味着在任何给定的时间都可以将PlayPiece视作4中事物之一,具体取决于应用变量的声明类型:

  • Object(因为任何对象都继承自Object) 。
  • GameShape(因为PlayerPiece扩展) 
  • PlayerPiece(因为这是它的本来身份) 。
  • Animatable(因为PlayerPiece实现Animatable) 。

以下全部都是合法的声明,请仔细观察:

 

这里只有一个对象——PlayerPiece类型的一个实例——因为有4种不同类型引用变量,它们全部都引用堆上的一个对象。一个流行的测验时上述变量中哪一个变量可以调用displayShape()方法?提示:上述4个声明中只有两个可用于调用displayShape()方法。

记住,编译器允许的方法调用只基于引用声明的类型,而不考虑对象的类型。因此,再次考虑4中引用类型——Object、GameShape、PlayerPiece和Animatable——这4中类型中有哪些知道displayShape()方法?

1. 对编译器来说,PlayerPiece IS-A GameShape,因此,编译器会认为:我看到声明类型是PlayerPiece,并且由于PlayerPiece扩展了GameShape,这意味着PlayerPiece继承了displayShape()方法,因此,PlayerPiece可用于调用displayShape()方法。

2. 还有,当使用声明为Animatable类型的引用PlayerPiece对象是,可以调用哪些方法呢?只能调用animate()方法。

3. 来自任何继承树的任何类也可以实现Animatable,因此,这意味着如果你具有一个方法,它带有声明为Animatable类型的变元。也就是说,你可以传入PlayerPiece对象、SpinningLogo对象以及实现Animatable的类的其他任何实例。

 

 

关于重写

我们还未介绍一个重要的部分:及时只有编译器知道生命的引用类型,JVM在运行时也会知道对象实际上是什么。这意味着即使使用GameShape引用变量底啊用PlayerPiece对象的displayShape()方法,如果PlayerPiece重写了displayShape()方法,JVM也会调用PlayerPiece的版本!JVM会在引用的另一端看到实际的对象,“看见” 它已经重写了声明的引用变量的方法,并且调用对象的实际类的方法。但是,要牢记另外一点:

 多态方法调用仅适用与实例方法。总是可以利用更一般的引用变量类型(超类或接口)引用一个对象,但是在运行时,基于实际对象(而不是引用类型)动态选择的唯一事物是实例方法,而不是静态方法,也不是变量。只有基于实际对象的类型动态地调用重写的实例方法。

 很难理解这段话吧!我现在还不是很理解,往后看看可能会对他有进一步的了解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值