Lectures
Lecture 1: The Essence of Objects
Lecture 2: Unions of Objects
Lecture 3: Classes of Objects:   Data Definitions
Lecture 4: Classes of Objects:   Interface Definitions
Lecture 5: Interface Design:   Independent and Extensible
Lecture 6: Parametric Interface Definitions and Methods
Lecture 7: Introducing Java:   Syntax and Semantics
Lecture 8: Union, Interfaces, and Lists in Java
Lecture 9: Testing in Java
Lecture 10: Parametric Interfaces in Java
Lecture 11: Computations on Many Structural Arguments:   Double Dispatch
Lecture 12: Parameterized Types and Double Dispatch; Abstracting Values
Lecture 13: Abstracting Computation with Function Objects
Lecture 14: Function Objects & Parameterized Types; Anonymous Classes & Lambda
Lecture 15: The Fundamental List Abstraction:   Fold
Lecture 17: Midterm Review
Lecture 16: Properties of Equality:   Reflexive, Symmetric, Transitive, and Total
Lecture 19: Structural Equality with Double Dispatch; Abstracting and Overridding
Lecture 18: More Double Dispatch
Lecture 22: Optional, Maps, Sets, and Lifting Default Code to Abstract Classes
Lecture 23: The Visitor Pattern
Lecture 24: Implementing Visitors; Bank Accounts
Lecture 25: Imperatives:   Implicit Communication via Side-Effects
Lecture 26: Aside:   List Exercises
Lecture 27: Imperatives:   Cyclic Data
Lecture 28: Imperatives:   Methods over Cylic Data
Lecture 29: BSTs, Maps, The Law of Hash  Code, and Comparable vs Comparators
Lecture 30: Random access and Array  Lists
Lecture 31: Implementing Hash Tables
Lecture 32: Resizing Hash Tables
Lecture 33: Simple Iterators
Lecture 34: List Iterators and Iterator Combinators
Lecture 35: List Iterators and Iterator Combinators
Lecture 36: Zippers
Lecture 37: Naive Tree Iterators
Lecture 38: Efficient Pre-Order Tree Iterators
Lecture 39: Drills
Lecture 40: Drill Solutions
Lecture 41: Wrap-up
6.12

Lecture 8: Union, Interfaces, and Lists in Java

Video.

An IDE for Java

We’re going to be using the IntelliJ integrated development environment (IDE) to develop and run Java programs. Like DrRacket, it will provide useful features to help us in the process of developing programs.

We’ll do a short demo in class and in lab.

Unions in Java: Traffic Lights

Let’s now turn back to modelling information in Java. So far we’ve seen how to represent compound data such as coordinates. Another common kind of data definition is a union data definition. Let’s look at a very simple union data definition (that we first looked at in class/0: traffic lights.

We define the union of objects in terms of their interface; the method signatures that each variant of the union has in common. In class/0 this takes the form:

;; A Light implements
;;
;; Compute the next traffic light after this one
;; next : -> Light

In Java, this interface definition looks like this:
interface Light {
// Compute the next traffic light after this one Light onTick();
}

In class/0, we would define a class and declare it implements the interface in a comment. In Java, we can declare the intention to implement the interface as part of the class definition:

class Red implements Light {
Red() {}
}

Nullary Constructor by Default. Note the Red constructor takes no arguments and does nothing, which is what we want since there are no fields in the Red class. As a side note: we can omit this nullary constructor, since it is the default constructor Java will use if no constructor is defined.

class Red implements Light {}

Now, this class says that it implements the Light interface, but so far it has not actually defined the next method as required by the Light interface.

The Java type system will catch this error for us. If you tried to compile this program as-is, there would be a compile-time error:

Error: Red is not abstract and does not override abstract method next() in Light.

In the IDE, this static error is often indicated with a red squiggly underlining of the class definition.

Let’s make a stub for next method:

class Red implements Light {
// Compute the next traffic light after this red light Light next() {
return this;
}
}

Visibility modifiers. As a small wrinkle, we need to place a visibility modifier on this method indicating that the method can be invoked from outside of the methods in this class:
class Red implements Light {
// Compute the next traffic light after this red light public Light next() {
return this;
}
}

This public keyword is the visibility modifier. Using it here indicates that next can be called from outside of the Red class, which is (implicitly) what’s required by the interface. The are also visibility modifiers private and protected. We will mostly ignore visibility issues for now and assume that methods are public and fields are private. We will add modifiers when needed to make programs type-check. For more details, see the Oracle tutorial.

We can define the other variants of Light, with method stubs:
class Red implements Light {
// Compute the next traffic light after this red light public Light next() {
return this;
}
}
 
class Yellow implements Light {
// Compute the next traffic light after this yellow light public Light next() {
return this;
}
}
 
class Green implements Light {
// Compute the next traffic light after this green light public Light next() {
return this;
}
}

Thinking through some examples, it’s easy to come up with the correct code for the method definitions:

class Red implements Light {
// Compute the next traffic light after this red light public Light next() {
return new Green();
}
}
 
class Yellow implements Light {
// Compute the next traffic light after this yellow light public Light next() {
return new Red();
}
}
 
class Green implements Light {
// Compute the next traffic light after this green light public Light next() {
return new Yellow();
}
}

So now we’ve seen our first union data definition in Java.

Grammar: Java with Interfaces

The grammar of Java programs has grown some now. In particular a program now consists of some number of class or interface definitions. Since a set of objects may be defined as either a class or interface, we use type-name to range over things defined as classes or interfaces. The grammar is also updated to have optional visibility modifiers on method definitions. Here are the revised parts of the grammar (only):

 

program

 ::= 

class-or-intf-defn*

 

class-or-intf-defn

 ::= 

class-defn

 

  |  

intf-defn

 

intf-defn

 ::= 

interface int-name { method-sigs }

 

field-decl

 ::= 

type-name field-name ;

 

method-sigs

 ::= 

 

  |  

method-sig ; method-sigs

 

method-sig

 ::= 

type-name meth-name ( param-list )

 

method-defn

 ::= 

[vis-modifier] method-sig { return expr ; }

 

vis-modifier

 ::= 

public

 

  |  

private

 

type-name

 ::= 

class-name

 

  |  

intf-name

 

intf-name

 ::= 

id

Recursive Unions in Java: Lists

TBD