Worksheet Subtyping

Table of Contents

1. Questions and Completion

If you have questions as you go through this worksheet, please feel free to post them on the discussion forum.

2. Dynamic Dispatch And Covariant Subtyping In Java

Consider the following program in Java. What will be printed when it runs?

Verify your answer by compiling and running the program.

interface I {
  void f ();
}

class A implements I { 
  public void f () { 
    System.out.println ("A"); 
  } 
}

class B extends A { 
  public void f () { 
    System.out.println ("B"); 
  } 
}

public class Dispatch1 {
  public static void main (String[] args) { 
    I[] arr1 = new I[] { new A (), new B () };
    A[] arr2 = new A[] { new A (), new B () };
    A[] arr3 = new B[] { new B (), new B () };

    for (int n = 0; n < arr1.length; n++) {
      arr1[n].f ();
      arr1[n] = new A ();
    }

    for (int n = 0; n < arr2.length; n++) {
      arr2[n].f ();
      arr2[n] = new A ();
    }

    for (int n = 0; n < arr3.length; n++) {
      arr3[n].f ();
      arr3[n] = new A ();
    }
  }
}

3. Subtyping Questions

3.1. Symmetric?

Is it true that subtyping is a symmetric relation? I.e., if Y<:X then X<:Y. If you answer no, give an example Java or Scala program that proves your point (it should fail to compile).

3.2. Transitivity?

Suppose W<:X, X<:Y, and List[Y]<:Z. Is it the case that List[W]<:Z?

3.3. Downcasting

Something is wrong with the method convert in the following Java program. Does it fail at compile time or at runtime?

Verify your answer by compiling and (perhaps) running the program.

public class Downcast {
  static class A           { int x; }
  static class B extends A { int y; }

  static B convert (A p) {
    B result = (B) p;
    return result;
  }

  public static void main (String[] args) {
    A r = new A ();
    r.x = 5;
    B s = convert (r);
    System.out.println (s);
  }
}

4. Subtyping And Variance In Scala

4.1. Covariant Lists

Verify that the List type is covariant in Scala by entering the following Scala program into the Scala REPL.

class B:
  def f (x:Int) : Int          = 1 

class C extends B:
  override def f (x:Int) : Int = 2
  def g () : Int               = 3

val xs1:List[B] = List (new B, new B)
val xs2:List[C] = List (new C, new C)
val xs3:List[B] = List (new B, new C)
val xs4:List[B] = xs2                
xs4 (1).f (0)                        

4.2. Invariant Arrays

Verify that the Array type is invariant in Scala by entering the following Scala program into the Scala REPL.

class B:
  def f (x:Int) : Int          = 1 

class C extends B:
  override def f (x:Int) : Int = 2
  def g () : Int               = 3

val xs1:Array[B] = Array (new B, new B)
val xs2:Array[C] = Array (new C, new C)
val xs3:Array[B] = Array (new B, new C)
val xs4:Array[B] = xs2
xs4 (0) = new B       
xs2 (0).g ()          

Author: James Riely

Created: 2024-04-17 Wed 17:41

Validate