CS61B笔记系列 10 Subtype Polymorphism vs. HoFs


10.1 Dynamic Method Selection Puzzle (Online Only)

10.1.1 A Typing Puzzle

上来先整一道题做做:

Suppose we have two classes: 有两个类

  • Dog: Implements bark() method. Dog 实现了 bark()
  • ShowDog: Extends Dog, overrides bark method. ShowDog 继承了 Dog ,override 了 bark()

Summarizing is-a relationships, we have:

  • Every ShowDog is-a Dog
  • Every Dog is-an Object.
    • All types in Java are a subtype of Object.

For each assignment, decide if it causes a compile error.

For each call to bark, decide whether:

  1. Dog.bark() is called,
  2. ShowDog.bark() is called, or
  3. A syntax error results.

The rules:

  • Compiler allows memory box to hold any subtype.
  • Compiler allows calls based on static type.
  • Overridden non-static methods are selected at run time based on dynamic type. 在运行时根据动态类型选择被覆盖的非静态方法。
    • Everything else is based on static type, including overloaded methods. Note: No overloaded methods for problem at left.
Object o2 = new ShowDog("M","C",25,512.2)
//is ShowDg is a Object?yes allowed

ShowDog sdx = ((ShowDog) o2);
// o2 的 static type 是 Object ,((ShowDog) o2)的 static type 是ShowDog  allowed
sdx.bark();
//showdog 有 bark 方法么?有,调用 showdog.bark

Dog dx = ((Dog)o2);
//尝试把 static type:Object变 Dog allowed
Dx.bark();
// 注意 此时的dx的 dynamic type 是 showdog,调用 showdog.bark

((Dog)o2).bark();
// o2:static:Object , (Dog):Dog ,dog有bark?有。但是还是一样,o2 的 dynamic type是showdog

Object o3 = (Dog) o2;
// o2 是Object,allowed
o3.bark();
// o3:static:Object 没有 bark ,编译失败

注意 Casting 这玩意 does not have any lasting effcet,只针对此表达式进行一个强制类型转换,不会对 static type 做改变,仅仅是为了类型检查而视为一个xx类

还有就是编译器仅仅通过静态类型来判断

10.1.2 Static Methods, Variables, and Inheritance

我们提出两个问题:

  • What if a subclass has variables with the same name as a superclass? 若子类有与超类同名的变量怎么办
  • What if subclass has a static method with the same signature as a superclass method?若子类具有与超类方法具有相同的静态签名咋办
    • For static methods, we do not use the term overriding for this. 覆盖 Overriding 仅仅适用于非静态方法

但是不讲嘿嘿嘿

10.2 Subtype Polymorphism 子类多态性

首先 Polymorphism 是什么 : “providing a single interface to entities of different types”为不同类型的实体提供一个单一的接口

Subtype Polymorphism 就是调用那个方法的区别取决于对象的类型

E:

Consider a variable deque of static type Deque:

  • When you call deque.addFirst(), the actual behavior is based on the dynamic type.
  • Java automatically selects the right behavior using what is sometimes called “dynamic method selection”.

也就是说我们对以一个 deque ,不知道是 linked 还是 基于数组的,都会调用 deque.addFirst() ,到时候会进行一个 dynamic methond selection

def print_larger(x, y, compare, stringify): # 顺带一提 这里会被叫做  callback 
    if compare(x, y):
        return stringify(x)
    return stringify(y)
def print_larger(x, y):
   if x.largerThan(y):
       return x.str()
   return y.str()

上段代码: Explicit HoF Approach

下段代码: Subtype Polymorphism Approach 这里是类做出了选择

10.3 DIY Comparison

教你写 max( ) 方法

10.3.1 how many compilation errors are there in the code shown?

public static Object max(Object[] items) {
  int maxDex = 0;
  for (int i = 0; i < items.length; i += 1) {
    if (items[i] > items[maxDex]) {
      maxDex = i;                 }}
  return items[maxDex];
}
public static void main(String[] args) {
  Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
                new Dog("Benjamin", 15)};
  Dog maxDog = (Dog) max(dogs);
  maxDog.bark();
}
https://raw.githubusercontent.com/biepin7/CloudForImg/master/20220412160626.png

明显是B , > 的使用

当然可以特意给dog类去写一个 maxDog 方法,但是不优雅

10.3.2 Solution : interface inheritance

然而 java 是不支持运算符重载的,所以我们用 ”接口继承 interface inheritance“

interface inheritance says what a class can do, in this case compare.

如何做呢:

Create an interface that guarantees a comparison method.

  • Have Dog implement this interface.
  • Write Maximizer class in terms of this interface.
public static OurComparable max(OurComparable[] items) { ...

具体实现:

public interface OurComparable {
   int compareTo(Object obj);
}
public class Dog implements OurComparable {
    public int compareTo(Object obj) {
        /** Warning, cast can cause runtime error! */
       Dog uddaDog = (Dog) obj;
       return this.size - uddaDog.size;
      } ...
public class Maximizer {
    public static OurComparable max(OurComparable[] a) {
    ...
}

我们使得 Dog are comparable ,而不是写了一个 max()

Dog[] dogs = new Dog[]{d1, d2, d3};
Dog largest = (Dog) Maximizer.max(dogs);

10.3.3 Comparable

使用 java 内置的 interface comparable

public class Dog implements Comparable<Dog> {

    @Override
    public int compareTo(Dog uddaDog) {
        //assume nobody is messing up and giving us
        //something that isn't a dog.
        return size - uddaDog.size;
    }
public class Maximizer {
    public static Comparable max(Comparable[] items) {

10.3.4 Comparators

def print_larger(T x, T y, comparator<T> c):
   if c.compare(x, y):
       return x.str()
   return y.str()

发表回复