本 Wiki 开启了 HTTPS。但由于同 IP 的 Blog 也开启了 HTTPS,因此本站必须要支持 SNI 的浏览器才能浏览。为了兼容一部分浏览器,本站保留了 HTTP 作为兼容。如果您的浏览器支持 SNI,请尽量通过 HTTPS 访问本站,谢谢!
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录前一修订版后一修订版 | 前一修订版 | ||
cs:programming:java:courses:gtx_cs1311x:oop_n_algorithms [2024/01/22 11:10] – [Polymorphism] codinghare | cs:programming:java:courses:gtx_cs1311x:oop_n_algorithms [2024/01/22 12:36] (当前版本) – [实例:扔骰子] codinghare | ||
---|---|---|---|
行 250: | 行 250: | ||
- 访问私有变量一定要通过 Accessor | - 访问私有变量一定要通过 Accessor | ||
- 除了 '' | - 除了 '' | ||
+ | - '' | ||
//Source code with comments//: {{ : | //Source code with comments//: {{ : | ||
====Inheritance==== | ====Inheritance==== | ||
行 933: | 行 934: | ||
====Polymorphism==== | ====Polymorphism==== | ||
**多态**(// | **多态**(// | ||
- | ==Java 处理多态的过程== | + | ===Java 处理多态的过程=== |
+ | <code js> | ||
+ | Canine pixy; | ||
+ | pixy = new Poodle(..); | ||
+ | pixy.bark(); | ||
+ | </ | ||
- Java 会首先查找声明中的类型(declar type) | - Java 会首先查找声明中的类型(declar type) | ||
- 找到后,再查找实例化的类型('' | - 找到后,再查找实例化的类型('' | ||
行 940: | 行 946: | ||
- 如果我们想通过该对象访问某些方法,那么这些方法在 declar type 中有没有声明且定义? | - 如果我们想通过该对象访问某些方法,那么这些方法在 declar type 中有没有声明且定义? | ||
如果上述条件都不满足,Java 编译器会认为该 assignment 是不合法的。 | 如果上述条件都不满足,Java 编译器会认为该 assignment 是不合法的。 | ||
+ | ==Legal Assignments== | ||
+ | Java 会对针对第一个问题进行所谓的 // | ||
+ | * 如果 declar type 是 class | ||
+ | * 检查 instantiate type 是不是 declar type 本身,或是其 subclass | ||
+ | 比如: | ||
+ | <code js> | ||
+ | //ok, pixy is a Poodle, Poodle is a dog | ||
+ | Dog pixy; | ||
+ | pixy = new Poodle(); | ||
+ | |||
+ | //error, pixy is a Dog, a Dog may not be a Poodle | ||
+ | Poodle pixy; | ||
+ | pixy = new Dog(...); | ||
+ | </ | ||
+ | 这种 //Is a// 的规则同样应用于将 argument 传递给 parameter 的过程中。这种情况下: | ||
+ | * argument 指向的类型是 object type | ||
+ | * parameter 指向的类型是 instantiate type | ||
+ | 比如: | ||
+ | <code js> | ||
+ | public class Human { | ||
+ | public void playFetch(Dog myPet) { | ||
+ | //.... | ||
+ | } | ||
+ | } | ||
+ | Dog richie = new Dog(...); | ||
+ | Poodle pixy = new Poodle(...); | ||
+ | |||
+ | //ok, richie is a Dog | ||
+ | owner.playFetch(richie); | ||
+ | //ok, pixy is a Poodle, Poodle is a Dog | ||
+ | owner.playFetch(pixy); | ||
+ | </ | ||
+ | |||
+ | * 如果 declar type 是 instance | ||
+ | * 检查 instantiate type 本身或是其任意父类(祖先)有没有**实现** interface | ||
+ | <WRAP center round important 100%> | ||
+ | 声明为相同 interface 类型的两个对象很可能不是互通的;比如车不能实例化为狗,即便车和狗都有“洗”的行为。 | ||
+ | </ | ||
+ | ==Method Calls== | ||
+ | 第二个需要检查的是 method 的调用: | ||
+ | * 如果 **declar type** 中包含了该 method,那是没有问题的,比如: | ||
+ | <code js> | ||
+ | //Canine defines bark() | ||
+ | //Poodle defines enterDogShow() | ||
+ | |||
+ | //declar type | ||
+ | Canine pixy; | ||
+ | Poodle richie = new Poodle(...); | ||
+ | pixy = richie; | ||
+ | |||
+ | //ok, bark() is defined in Canine | ||
+ | pixy.bark(); | ||
+ | |||
+ | //error, Canine doesn' | ||
+ | pixy.enterDogShow(); | ||
+ | </ | ||
+ | <WRAP center round tip 100%> | ||
+ | method call **只考虑声明类型**中是否存在该函数的定义,不考虑对象类型;**除非对象类型中存在着该 method 的 overriding**(详情见之后的动态绑定) | ||
+ | </ | ||
+ | ===Casting=== | ||
+ | 上述例子中,如果我们希望使用 '' | ||
+ | <code js> | ||
+ | //ok, in case of using enterDogshow(), | ||
+ | // !!!notice the praentheses!!! | ||
+ | ((Poodle)pixy).enterDogShow(); | ||
+ | </ | ||
+ | Casting 可以在继承关系树上**向上**,或是**向下**进行(注意不是 is-a 或者 has-a 的关系不行!),得到的结果是一个**临时的**转换后的 Object 类型(的引用)。我们只需要确保 Casting 之后的**类型可以访问被调用的方法**即可。 | ||
+ | <WRAP center round info 100%> | ||
+ | Casting 只是生成了一个**临时的**,对应的 Object 类型的引用。'' | ||
+ | </ | ||
+ | |||
+ | ==Casting 潜在的问题== | ||
+ | Casting 带来了一个问题。来看以下例子: | ||
+ | <code js> | ||
+ | Canine dg; | ||
+ | dg = new Dog(...); | ||
+ | |||
+ | //is thi legal? | ||
+ | ((Poodle)dg).enterDogShow(); | ||
+ | </ | ||
+ | 这种情况下, | ||
+ | ===Dynamic Binding=== | ||
+ | 在检测 method call 是否合法的同时,JVM 还会同时在**运行期**检测哪一个版本最适合当前的 call。处理该调用匹配的过程被称为**动态绑定**(// | ||
+ | * 如果 object type 和 declar type 中存在不一样的实现(即 object type 中有重写),那么选择 object type 的版本 | ||
+ | <code js> | ||
+ | //if Canine & Poodle both have a bark() implementation | ||
+ | Canine pixy; | ||
+ | pixy = new Poodle(...); | ||
+ | |||
+ | //call Poodle.bark() | ||
+ | pixy.bark(); | ||
+ | </ | ||
+ | * 如果 object type 中不存在重写,JVM 会按照继承树**逐级往上查询**,直到找到对应的实现 | ||
+ | <code js> | ||
+ | //if Canine & Dog both have a bark() implementation, | ||
+ | Canine pixy; | ||
+ | pixy = new Poodle(...); | ||
+ | |||
+ | //call Dog.bark() | ||
+ | pixy.bark(); | ||
+ | </ | ||