前言
我们在平时的开发编码中,都会用到上溯造型和下溯造型,只是我们并不知道他的官方叫法而已, 上溯造型跟继承和多态,以及动态绑定的关系很密切 ,关于这几个概念后面会有涉及到他们的概念。
继承和合成
继承:它的本质就是为了使得代码复用(可以基于已经存在的类构造一个新类。继承已经存在的类就可以复用这些类的方法和域。在此基础上,可以添加新的方法和域,从而扩充了类的功能。)
合成:在新类里创建原有的对象称为合成。这种方式可以重复利用现有的代码而不更改它的形式。
|
上溯造型
这个术语缘于继承关系图的传统画法:将基类至于顶部,而向下发展的就是派生类(子类),发送给父类的消息亦可发给衍生类,父类包含子类。假设把子类赋值给父类,这个过程就称之为上溯造型— 这个时候只能够调用父类父类的方法,子类特有的方法不能够调用,子类变窄
|
|
这个时候为什么输出是:子类覆盖父类的方法,而不是父类的方法,这个涉及到动态绑定。后面再讲
由于upcasting(Animal animal)方法的参数是 Animal类型的,因此如果传入的参数是 Animal的子类,传入的参数就会被转换成父类Animal类型,这样你创建的Dog对象能使用的方法只是Animal中的签名方法;也就是说,在上溯的过程中,Dog的接口变窄了,它本身的一些方法(例如实现了 DoorGod的guard方法)就不可见了。如果你想使用Dog中存在而Animal中不存在的方法(比如guard方法),编译时不能通过的。由此可见,上溯造型是安全的类型转换。
如果Dog在上溯造型过程中想使用 DoorGod的guard方法,那么需要配合下溯造型和安全检查,来进行强制转换,讲Animal 下溯为 Dog类型。
注意的是:下溯是不安全的,由父类转化为子类,所以需要加上判断。
下溯造型
将基类转化为衍生类,不安全的操作,可能会引发ClassCastException。
|
我们在使用注解实现请求方法的登录控制 登录拦截器里面有段关键代码使用的就是下溯造型
为什么使用上溯和下溯造型
上面的例子我们发现,关键的代码是upcasting方法,为什么在调用upcasting方法时要有意忽略调用它的对象类型呢?如果让upcasting方法简单地获取Dog句柄似乎更加直观易懂,但是那样会使衍生自Animal类的每一个新类都要实现专属自己的upcasting方法:例如Cat会实现一个重复的upcasting(Cat cat )这样的方法。
实现多态的好处和代码复利用。
动态绑定
在上面的upcasting方法,测试例子输出的是子类的方法,而非是父类的方法,但是我们使用的是父类去调用这些方法,为什么输出不是父类的呢?
upcasting它接收的是Animal句柄,当执行speak和eat方法时时,它是如何知道Animal句柄指向的是一个Dog对象而不是Cat对象呢?编译器是无从得知的,这涉及到接下来要说明的绑定问题。
Java实现了一种方法调用机制,可在运行期间判断对象的类型,然后调用相应的方法,这种在运行期间进行,以对象的类型为基础的绑定称为动态绑定。除非一个方法被声明为final,Java中的所有方法都是动态绑定的。
静态方法的绑定
他跟普通的方法不同,子类和父类方法都是静态的,子类如果去掉父类编译会错误
|
对于静态方法而言,不管父类引用指向的什么子类对象,调用的都是父类的方法。
总结
上溯造型和动态绑定实际上就是多态的体现,下溯造型是为了解决因为上溯而导致衍生类功能变小的问题,继承则是上溯和下溯以及动态编译的基础。