SE450: Lecture 2 (Objects as Functions)

Contents [0/47]

Overview of Today's Class [1/47]
Homework 1: Solution [2/47]
Packages: Compilation Units [3/47]
Packages: Compiling with Packages [4/47]
Packages: Compiling with Packages [5/47]
Packages: The Classpath [6/47]
Packages: Fully Qualified Names [7/47]
Packages: Package Diagrams [8/47]
Scope: Hiding [9/47]
Scope: Java Scope Rules [10/47]
Scope: Visibility in Java [11/47]
Scope: Nested Packages [12/47]
Scope: Nested Classes [13/47]
Encapsulation: Encapsulation and Abstraction [14/47]
Encapsulation: Provider/Consumer [15/47]
Encapsulation: Encapsulation in Java [16/47]
Encapsulation: Interfaces everywhere [17/47]
Encapsulation: Invariants, Preconditions, and Postconditions [18/47]
Encapsulation: Designing interfaces [19/47]
Encapsulation: Priniciple of Least Knowledge [20/47]
Types: Class as Type 1 [21/47]
Types: Class as Type 2 [22/47]
Types: Interface as Type 1 [23/47]
Types: Interface as Type 2 [24/47]
Types: Naming the intersection [25/47]
Types: Using Generic Methods [26/47]
Types: Declared and Actual Types [27/47]
Types: Subtyping [28/47]
Types: Many terms [29/47]
Types: Subtyping [30/47]
Types: Multiple inheritance [31/47]
Types: Abstraction [32/47]
Types: Principle of Substitutivity [33/47]
Types: Late Binding [34/47]
Types: Casting [35/47]
Types: Coercion [36/47]
Patterns: Introduction [37/47]
Patterns: GoF principles [38/47]
Patterns: Architecture and Software Design [39/47]
Patterns: The Quality without a Name [40/47]
Patterns: A Pattern Language [41/47]
Patterns: A Timeless Way of Building [42/47]
What if you want class names to be hidden from clients? [43/47]
Static Factory Example [44/47]
Function Objects: Strategy [45/47]
Function Objects: Command [46/47]
Function Objects: Homework 2 [47/47]

Overview of Today's Class [1/47]

Homework 1: Solution [2/47]

Let's discuss HW1, looking at my solution, which will be posted on COL tomorrow around noon.

Packages: Compilation Units [3/47]

A java compilation-unit (file) contains:

What if a file contains a public class/interface?

What if the package declaration is absent?

If a class/interface is public, the filename must correspond to the class/interface name. As a result, each file may contain at most one public class or interface.

If the package declaration is absent, then the classes belong to a unnamed default package.

Packages: Compiling with Packages [4/47]

For example, the following code declares class types.simplePackage.Main:

file:types/simplePackage/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
package types.simplePackage;
public class Main {
  private Main() {}
  public static void main (String[] argv) {
    System.out.println("Hello Packages!");
  }
}

How do you compile it?

Packages: Compiling with Packages [5/47]

To compile the code, place it in the file types\simplePackage\Main.java and run the compiler:

> javac types\simplePackage\Main.java

The compiler produces the file types\simplePackage\Main.class. To execute the static types.simplePackage.Main.main() method, run the interpreter:

> java types.simplePackage.Main

Note that the compiler, rather irritatingly, does not complain if the directory name and package name disagree; however, the JVM does.

Packages: The Classpath [6/47]

The java interpreter looks for packages along its classpath.

Suppose types is in directory d:\se450\code\build\classes. Then we can run Hello at any time by typing:

> java -classpath d:\se450\code\build\classes types.simplePackage.Main

or

> set classpath="%classpath%;d:\se450\code\build\classes"
> java types.simplePackage.Main

Note that java will ignore classes in the current directory unless . is in the classpath. If you are in a directory with Main.class and java replies

> java Main
Exception in thread "main" java.lang.NoClassDefFoundError: Main

try:

> java -classpath . Main

In windows, you can set your classpath variable permanently by adding a line at the end of c:\autoexec.bat and restarting your computer. For example:

set classpath=".;d:\se450\lib\ant.jar;%classpath%"

If DOS gives you the error "Out of environment space", then apply the solution found here: http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q230205&

In win2k, NT, XP you can also use, for example:

start |
  settings |
    control panel |
      system |
        advanced |
          environment variables |
            new | (or modify)
              Variable Name: classpath
              Variable Value: .;d:\se450\lib\ant.jar;(whatever was there before)

Packages: Fully Qualified Names [7/47]

Java classes are accessed from other packages using fully-qualified names, such as java.awt.Component or types.simplePackage.Main.

new java.util.LinkedList();

One can also use bare class names in other packages by importing the relevant classes.

import java.util.LinkedList;
new LinkedList();

Import statements do nothing but help resolve names.

Packages: Package Diagrams [8/47]

A top-level package diagram typically shows all of the packages in a system. Sometimes it also includes the public classes/interfaces within each package (usually by name only--no fields or methods listed). You can then show the dependencies between these public portions of the packages.

Here is a small example:

    +---+                       +---+              
    | x |                       | y |              
    +---+-------------+         +---+-------------+
    |                 |         |                 |
    | +-------------+ |         | +-------------+ |
    | |<<interface>>|<----+-------|Main         | |
    | |      I      | |   |     | +-------------+ |
    | +-------------+ |   |     |                 |
    |                 |   |     +-----------------+
    |  +----------+   |   |
    |  |<<static>>|<------+
    |  | IFactory |   |
    |  +----------+   |
    |                 |
    +-----------------+

There are two packages, x and y. x has two public classes: I is an interface and IFactory has only static methods. y has one public class: Main. y.Main depends on x.I and x.IFactory.

Note that the diagram does not show "intra-package" dependencies, only "inter-package" dependencies; that is, we do not show dependencies within a package, but only between packages.

Here is a more abstract version:

    +---+             +---+    
    | x |             | y |    
    +---+---+         +---+---+
    |       |         |       |
    |       |<--------|       |
    |       |         |       |
    +-------+         +-------+

A system document would usually also have a class diagram for each package, showing in more detail how the package is implemented.

Scope: Hiding [9/47]

What is scope?

What is hiding (occlusion)?

What is visibility?

class C {
  int i;
  float f;          
  void m(int f) {
    // field f is hidden
    for (int i = f; i--; i>0) {
       // field i is hidden
    }
  }
}

Scope: Java Scope Rules [10/47]

The dot operator (.) affects scope.

In C++, there are three operators that affect scope: ., -> and ::.

The names in scope on the right of the java dot operator depend on the compile-time type of the left expression.

Scope: Visibility in Java [11/47]

What is public visibilty?

What is private visibility?

What is package-private visibility? (aka default, package, friendly)

What is protected visibility?

file:types/visibility/x/A.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package types.visibility.x;
public class A {
  private int x0;
  int x1;
  protected int x2;
  public int x3;

  int fx(A that) {
    return this.x0 + this.x1 + this.x2 + this.x3
        + that.x0 + that.x1 + that.x2 + that.x3;
  }
}

class B {
  int gx(A that) {
    return that.x0 + that.x1 + that.x2 + that.x3;
  }
}

file:types/visibility/y/C.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
package types.visibility.y;
import  types.visibility.x.A;
class C extends A {
  int fy(C that) {
    return this.x0 + this.x1 + this.x2 + this.x3
        + that.x0 + that.x1 + that.x2 + that.x3;
  }
}

class D {
  int gy(A that) {
    return that.x0 + that.x1 + that.x2 + that.x3;
  }
}

Scope: Nested Packages [12/47]

Is there any significance to nested packages?

No.

Scope: Nested Classes [13/47]

Is there any significance to nested classes?

Not if they are static.

non-static nested classes are special.

Encapsulation: Encapsulation and Abstraction [14/47]

Encapsulation is about hiding details -- the details are not accessible outside the unit of encapsulation.

Large organizations function because not everyone needs to know every detail all the time -- they break down when too many people need to know too much.

For example, Math.random():double computes a pseudo-random number, but the details are hidden.

Code provider versus client programmer.

The provider's code is encapsulated. The client sees an abstraction.

Encapsulation: Provider/Consumer [15/47]

OO Design is about defining good abstractions (boundaries).

Abstractions distribute responsibilities.

Code provider versus client programmer -- there is always contract between the two.

Where are the contracts in Java?

Java Equality as example of informal contract: java.lang.Object#equals(java.lang.Object)

Encapsulation: Encapsulation in Java [16/47]

Java has four levels of encapsulation:

There is actually a bit more. For example, outside of the source language, one can seal jar files so that packages are closed.

Encapsulation: Interfaces everywhere [17/47]

Java uses the keyword interface to define the interface of an object class.

Encapsulation: Invariants, Preconditions, and Postconditions [18/47]

Definition: the interfaces of classes are viewed as contracts that specify benefits and obligations of both the client and the supplier (the class itself). (Bertrand Meyer)

We can enhance interfaces by using preconditions/postconditions and invariants:

  1. Precondition - must be true to make the call. Indicates the bug is in the caller.
  2. Postcondition - must be true after the call. Indicates the bug is in the provider (or in the precondition assertion!)
  3. Invariant - must always be true (after a successful instantiation of the class, or even true for static methods if there is no object of the class created). It will be true before and after each method invocation. Indicates the bug could be in either the caller or the provider.

You can define these conditions as constraints in the UML. Just put the text describing the constraint in { }. There is also a more formal Object Constraint Language available to define constraints.

The programming language Eiffel has DBC built in. Two classes interact via a contract. A breach of contract is a bug. Eiffel provides the ability for all assertions to be propogated to subclasses, and assertions in interfaces apply to implementing classes. Read this article for some more information on DBC in Eiffel.

Encapsulation: Designing interfaces [19/47]

What makes a good method?

What makes a good class?

What makes a good package?

Cohesion - should be describable in one short sentence.

Encapsulation: Priniciple of Least Knowledge [20/47]

The paranoia principle: Hide as much as possible

Said differently: don't make commitments you don't need to make.

Types: Class as Type 1 [21/47]

file:types/point1/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package types.point1;
import java.awt.Color;
final class CartesianPoint {
  private final double x;
  private final double y;
  private final Color color;
  public CartesianPoint(double x, double y, Color color) {
    this.x = x;
    this.y = y;
    this.color = color;
  }
  public double getX() { return x; }
  public double getY() { return y; }
  public Color getColor() {
    System.out.println("It's Cartesian!");
    return color;
  }
}
public class Main {
  private Main() {}
  public static void main(String[] args) {
    CartesianPoint p1 = new CartesianPoint(0,0,Color.RED);
    CartesianPoint q1 = new CartesianPoint(1,1,Color.BLUE);
  }
}

What are the types of p1 and q1?

Types: Class as Type 2 [22/47]

file:types/point2/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package types.point2;
import java.awt.Color;
final class PolarPoint {
  private final double theta;
  private final double r;
  private final Color color;
  public PolarPoint(double theta, double r, Color color) {
    this.theta = theta;
    this.r = r;
    this.color = color;
  }
  public double getX() { return r*Math.cos(theta); }
  public double getY() { return r*Math.sin(theta); }
  public Color getColor() {
    System.out.println("It's Polar!");
    return color;
  }
}
public class Main {
  private Main() {}
  public static void main(String[] args) {
    PolarPoint r1 = new PolarPoint(0,0,Color.RED);
  }
}

What is the type of r1?

Types: Interface as Type 1 [23/47]

file:types/point3/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package types.point3;
import java.awt.Color;
interface Point {
  double getX();
  double getY();
}
final class CartesianPoint implements Point {
  /* ... */
}
final class PolarPoint implements Point {
  /* ... */
}
public class Main {
  private Main() {}
  public static void main(String[] args) {
    CartesianPoint p1 = new CartesianPoint(0,0,Color.RED);
    CartesianPoint q1 = new CartesianPoint(1,1,Color.BLUE);
    PolarPoint r1 = new PolarPoint(0,0,Color.RED);

    Point p2 = p1;
    Point q2 = q1;
    Point r2 = r1;
  }
}

What are the types of p2, q2, r2?

Types: Interface as Type 2 [24/47]

file:types/point4/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package types.point4;
import java.awt.Color;
interface Colored {
  Color getColor();
}
interface Point {
  double getX();
  double getY();
}
final class CartesianPoint implements Colored, Point {
  /* ... */
}
final class PolarPoint implements Colored, Point {
  /* ... */
}
public class Main {
  private Main() {}
  public static void main(String[] args) {
    CartesianPoint p1 = new CartesianPoint(0,0,Color.RED);
    CartesianPoint q1 = new CartesianPoint(1,1,Color.BLUE);
    PolarPoint r1 = new PolarPoint(0,0,Color.RED);

    Point p2 = p1;
    Point q2 = q1;
    Point r2 = r1;

    Colored p3 = p1;
    Colored q3 = q1;
    Colored r3 = r1;
  }
}

What are the types of p3, q3 and r3?

Types: Naming the intersection [25/47]

file:types/point5/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package types.point5;
import java.awt.Color;
interface Colored {
  Color getColor();
}
interface Point {
  double getX();
  double getY();
}
interface ColoredPoint
extends Colored, Point
{ }
final class CartesianPoint implements ColoredPoint {
  /* ... */
}
final class PolarPoint implements ColoredPoint {
  /* ... */
}
public class Main {
  private Main() {}
  public static void printColoredPoint(ColoredPoint cp) {
    System.out.println(cp.getX());
    System.out.println(cp.getY());
    System.out.println(cp.getColor());
  }
  public static void main(String[] args) {
    printColoredPoint(new CartesianPoint(0,0,Color.RED));
    printColoredPoint(new PolarPoint(0,0,Color.RED));
  }
}

Types: Using Generic Methods [26/47]

file:types/point6/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package types.point6;
import java.awt.Color;
interface Colored {
  Color getColor();
}
interface Point {
  double getX();
  double getY();
}
final class CartesianPoint implements Colored, Point {
  /* ... */
}
final class PolarPoint implements Colored, Point {
  /* ... */
}
class Main {
  private Main() {}
  public static <T extends Point & Colored> void printColoredPoint(T cp) {
    System.out.println(cp.getX());
    System.out.println(cp.getY());
    System.out.println(cp.getColor());
  }
  public static void main(String[] args) {
    printColoredPoint(new CartesianPoint(0,0,Color.RED));
    printColoredPoint(new PolarPoint(0,0,Color.RED));
  }
}

Types: Declared and Actual Types [27/47]

Declared type = Static type = Compile-time type.

Actual type = Dynamic type = Run-time type.

Java community refers to type of variable versus class of object.

Types: Subtyping [28/47]

Objects may inhabit more than one type.

  Object x = new Integer(1);

If all of the objects in D are also in B, we say:

This is called subtype polymorphism.

Common notation for theorists: D <: B.

Subtype related to subset -- values(D) is a subset of values(B)

Types: Many terms [29/47]

Relating interfaces to interfaces (J <: I)

Relating classes to interfaces (D <: I)

Relating classes to classes (D <: B)

Types: Subtyping [30/47]

What is subtyping in Java? For any class or interface C:

What is subclassing?

Types: Multiple inheritance [31/47]

Java 8 allows default implementations in interface.

There are restrictions to prevent issues caused by multiple inheritance in C++.

file:types/multipleInheritance1/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package types.multipleInheritance1;

/* 
 * Uncommenting h or g below causes interface K to fail to compile
 * "The default method h() inherited from I2 conflicts with another method inherited from I1"
 * 
 * Uncommenting toString below causes I1 to fail to compile, with error:
 * "A default method cannot override a method from java.lang.Object"
 */
interface I1 { 
  public void f ();
  default public void g () { System.out.println ("I1.g"); }
  //public void h ();
  //default public String toString () { return "I1"; }
}
interface I2 {
  public void f ();
  //default public void g () { System.out.println ("I2.g"); }
  default public void h () { System.out.println ("I2.h"); }
}

interface K extends I1, I2 { }

class C implements K { 
  public void f () { System.out.println ("C.f"); } 
}
public class Main {
  public static void main (String[] args) {
    C x = new C ();
    x.f ();
    x.g ();
    x.h ();
  }
}

file:types/multipleInheritance2/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package types.multipleInheritance2;

/* 
 * The "diamond of death" is not a problem in java, since multiple inheritance
 * is only possible for interfaces, and interfaces use "virtual inheritance" and
 * does not allow interfaces to have fields (no multiple-inheritance of state)
 * 
 * See
 * http://stackoverflow.com/questions/137282/how-can-you-avoid-the-diamond-of-death-in-c-when-using-multiple-inheritance
 * http://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html
 */
interface I0 {
  public void f ();
}
interface I1 extends I0 { 
  default public void g () { System.out.println ("I1.g"); }
}
interface I2 extends I0 {
  default public void g () { System.out.println ("I2.g"); }
}

/* It is possible to inherit conflicting defaults, as long as you don't use them!
 * If you comment out the definition of g in C or K below, you will get an error!
 */
class C implements I1, I2 { 
  public void f () { System.out.println ("C.f"); } 
  public void g () { System.out.println ("C.g"); } 
}
interface K extends I1, I2 { 
  default public void g () { System.out.println ("I2.g"); }
}
public class Main {
  public static void main (String[] args) {
    C x = new C ();
    x.g ();
  }
}

Types: Abstraction [32/47]

We can look at an object at progressively more abstract types.

Consider java.util.LinkedList:

file:types/abstractTypes/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
package types.abstractTypes;
public class Main {
  private Main() {}
  public static void main(String[] args) {
    java.util.LinkedList<?> o1 = new java.util.LinkedList<>();
    java.util.AbstractSequentialList<?> o2 = o1;
    java.util.AbstractList<?> o3 = o1;
    java.util.AbstractCollection<?> o4 = o1;
    java.lang.Object o5 = o1;

    java.util.List<?> i1 = o1;
    java.util.Collection<?> i2 = o1;

    java.io.Serializable i3 = o1;
    java.lang.Cloneable i4 = o1;
  }
}

There are nine references to a single object.

Each reference has a different set of capabilities.

Types: Principle of Substitutivity [33/47]

The Principle of Substitutivity (aka Liskov Substitution Principle): Subtypes should obey the behaviors expected by their supertypes.

Would it be okay if StringBuilder extended String?

void f(StringBuilder b, String s) {
  String t1 = new String(s);   // copy s
  b.append("astrophe");
  String t2 = new String(s);   // copy s again
  Assert.assertEquals(t1,t2);  // t1 and t2 should be the same
}

StringBuilder b = new StringBuilder("cat");          
f(b,b);

Would it be okay if String extended StringBuilder?

String s = new String();
StringBuilder b = s;
s.append(); // compiler error!  message not understood!

Some dubious interfaces:
java.lang.Cloneable
java.util.Iterator.

Types: Late Binding [34/47]

The actual type of an object -- along with the object state -- determines message response.

Actual type of receiver cannot be determined statically!

Colored p3, r3;
p3.getColor(); // prints "Cartesian"
r3.getColor(); // prints "Polar"

The actual method is bound late (ie, determined at run-time).

This is implemented using virtual function tables (aka, vtables).

Types: Casting [35/47]

What is a downcast, upcast, crosscast?

How are casts checked by the compiler?

How are casts checked by the runtime system?

file:types/casting/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package types.casting;

interface Animal { default public String f () { return "Animal"; } }
interface Fish extends Animal { default public String f () { return "Fish"; } }
interface Bird extends Animal { default public String f () { return "Bird"; } }
class Cod implements Fish { public String f () { return "Cod"; } }
class Owl implements Bird { public String f () { return "Owl"; } }

public class Main {
  private Main() {}
  public static void main(String[] args) {
    Cod cod = new Cod ();
    Owl owl = new Owl ();
    
    /* Implicit upcasts always compile and run ok */
    Animal aCod = cod;
    Animal aOwl = owl;
    
    /* Explicit upcast  causes an unnecessary cast warning */
    //Animal aCod2 = (Animal) cod;

    /* Explicit downcasts always compile, but may cause runtime errors */
    //Fish f1 = aCod;        // implicit downcast: compiler error
    //Fish f2 = (Fish) aOwl; // explicit downcast: runtime error
    Fish f3 = (Fish) aCod;   // explicit downcast: runtime success

    /* Crosscasting to a class is disallowed by the compiler */
    //Cod f4 = (Cod) owl;          // crosscast: compiler error
    
    /* Crosscast can be replaced by upcast+downcast */
    //Cod f5 = (Cod) (Animal) owl; // upcast+downcast: runtime error

    /* Crosscasting to an interface is allowed by the compiler */
    //Fish f6 = (Fish) owl;        // crosscast: runtime error
    
    /* Casting changes the declared type, but not the actual type */
    System.out.println("Animal: " + aCod.f());
    System.out.println("Fish:   " + f3.f());
    System.out.println("Cod:    " + cod.f());
  }
}
The rules are as follows 

  class A {}
  class B extends A {}
  class C extends A {}

Upcast goes from subtype to supertype: (A)(new B())
Downcast goes from supertype to subtype: (B)(new A())
Any other cast is a "cross cast"

At compile time:
Cast to interface type is always allowed.
Cast to class type is allowed if the it is an upcast or a downcast.
The declared type of the cast expression is changed:

      new B()  has declared type B
  (A)(new B()) has declared type A

At runtime:
Casts are checked to ensure validity (ClassCastException if not)
The actual type of the object is unchanged:

      new B()  has actual type B
  (A)(new B()) has actual type B

Output is:

Object n2=3.14
Number n2=3.14
Float  n2=3.14

Types: Coercion [36/47]

Coercion is very different from casting.

Java uses the same syntax for both concepts.

Coercion for base types. Casting for Object types.

Coercion changes the actual type of the object -- Casting changes only the declared type.

file:types/coercion/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package types.coercion;
class Main {
  private Main() {}
  @SuppressWarnings("cast")
  public static void main(String[] args) {
    int i0 = 1;
    float f0 = i0;         // compiles ok, runs ok (implicit up-coercion)
    float f1 = (float) i0; // compiles ok, runs ok (explicit up-coercion)

    float f2 = 1.42f;
    //  int i2 = f2;       // compiler error (implicit down-coercion)
    int i3 = (int) f2; // compiles ok, runs ok (explicit down-coercion)

    // Note that coercion changes the actual value, not just the
    // declared type.
    float f3 = i3;
    System.out.println("f2=" + f2);
    System.out.println("f3=" + f3);
  }
}
class CoercionOrdering {
  private CoercionOrdering() {}
  public static void showingCoercionOrder() {
    // booleans and object types do not coerce
    // use ?: to convert booleans to other types
    // use ?: also for object types
    boolean p = false;
    int j = p ? 1 : 0;
    Object o = null;
    int k = (null==o) ? 0 : 1;

    // char and short are both 16 bit, but mutually incomparable
    char  c = '\0';
    short z = 0;
    z = (short) c;
    c = (char) z;

    // number types from bottom to top
    byte   b = 0;
    short  s = b;
    int    i = s;
    long   l = i;
    float  f = l;
    double d = f;

    // number types from top to bottom, losing precision
    f = (float) d;
    l = (long) f;
    i = (int) l;
    s = (short) i;
    b = (byte) s;
  }
}

Output is:

f2=1.42
f3=1.0

Patterns: Introduction [37/47]

Goals:

Patterns: GoF principles [38/47]

In the GoF patterns book, we see a few principles repeated again and again. These principles shape the pattern design and intent in most of the patterns we will study. They are:

The last one is the opposite of focusing on the cause of redesign. Instead of focusing on what might force a change to a design, consider what you want to be able to change without redesign. The focus is on encapsulating the concept that varies, a theme of many design patterns [GoF p29]

Patterns: Architecture and Software Design [39/47]

There are similarity between architecture and software design:

Christopher Alexander suggested that all buildings can be designed using combinations of a relative small number of patterns.

He starts out trying to understand beauty.

Patterns: The Quality without a Name [40/47]

You know beauty when you see it, but it is hard to say exactly what it is.

There is a central quality which is the root criterion of life and spirit in a man, a town, a building, a wilderness. This quality is objective and precise, but cannot be named.

The search which we make for this quality, in our own lives, is the central search of any person, and the crux of any individual person's story. It is the search for those moments and situations when we are most alive.

Alexander

The Timeless Way of Building [Amazon, AddAll]

by Christopher Alexander (Oxford, 1979)

A Pattern Language [Amazon, AddAll]

by Christopher Alexander (Oxford, 1977)

wiki:ChristopherAlexander

http://patternlanguage.com/

http://patternlanguage.com/sampleOnly/archive/ieee/ieeetext.htm

http://stanford-online.stanford.edu/courses/ee380/001129-ee380-100.asx

http://www.math.utsa.edu/sphere/salingar/Chris.text.html

Patterns: A Pattern Language [41/47]

What words can be used to describe beautiful things?

Patterns are discovered, not invented.

To reach the quality without a name we must then build a living pattern language as a gate.

... the rich and complex order of a town can grow from thousands of creative acts. For once we have a common pattern language in our town, we shall all have the power to make our streets and buildings live, through our most ordinary acts. The language, like a seed, is the genetic system which gives our millions of small acts the power to form a whole.

Patterns: A Timeless Way of Building [42/47]

Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.

What if you want class names to be hidden from clients? [43/47]

What if class names are not stable? (I have the shapes Circle and Square, but may generalize later to allow ellipses and rectangles.)

Consider using a static factory:

Static Factory Example [44/47]

Notable in the example is the different way invariants are handled.

Person checks invariants in the constructor (throwing exceptions from the factory method if necessary).

SSN checks invariants in the factory method. Exactly one instance may violate the invariants: SSN.INVALID may be used for persons with no SSN.

file:factory/person/SSN.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
package factory.person;
public interface SSN extends Comparable<SSN> {
  public String toString();
  public long toLong();
  public static final SSN INVALID = new SSNObj("000000000");
}

file:factory/person/Person.java [source] [doc-public] [doc-private]
01
02
03
04
05
package factory.person;
public interface Person extends Comparable<Person> {
  public String name();
  public SSN ssn();
}

file:factory/person/PersonFactory.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package factory.person;
import java.util.Random;
public class PersonFactory {
  private PersonFactory() {}
  static private Random random = new Random();
  static public SSN newSSN(String s) {
    final int REQUIREDLENGTH = 9;
    if (null == s || REQUIREDLENGTH != s.length())
      throw new IllegalArgumentException();
    boolean someNonZeroDigit = false;
    for (int i=0; i<REQUIREDLENGTH; i++) {
      char c = s.charAt(i);
      if (!Character.isDigit(c))
        throw new IllegalArgumentException();
      if (0 != Character.digit(c,10))
        someNonZeroDigit = true;
    }
    if (!someNonZeroDigit)
      throw new IllegalArgumentException();
    return new SSNObj(s);
  }
  static public Person newRandomPerson() {
    return new PersonObj(Integer.toString(random.nextInt()),SSN.INVALID);
  }
  static public Person newPerson(String name, String ssn) {
    return new PersonObj(name,ssn);
  }
  static public Person newPerson(String name, SSN ssn) {
    return new PersonObj(name,ssn);
  }
}

final class SSNObj implements SSN {
  final private String s;
  final private long l;
  SSNObj(String s) {
    this.s = s;
    this.l = Long.parseLong(s);
  }
  public String toString() { return s; }
  public long toLong() { return l; }
  // TODO: define equals, hashcode, compareTo
  public int compareTo(SSN that) { return -1; }
}

final class PersonObj implements Person {
  final private String name;
  final private SSN ssn;
  PersonObj(String name, SSN ssn) {
    if (null == name || 0 == name.trim().length())
      throw new IllegalArgumentException();
    this.name = name.trim();
    this.ssn = ssn;
  }
  PersonObj(String name, String ssn) {
    this(name,PersonFactory.newSSN(ssn));
  }
  public String name() { return name; }
  public SSN ssn() { return ssn; }
  // TODO: define equals, hashcode, compareTo
  public int compareTo(Person that) { return -1; }
}

file:factory/person/main/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
package factory.person.main;
import factory.person.Person;
import factory.person.PersonFactory;
public class Main {
  private Main() {}
  public static void main(String[] args) {
    Person p = PersonFactory.newPerson("Bob Jones","123456789");
    System.out.println(p);
  }
}

Function Objects: Strategy [45/47]

We know how to do part of an algorithm, but not all.

Example: filter values in a list based on a predicate.

Example: sort values in a list based on a comparison operator.

Example: apply a function to every value in a list, creating a new list.

Let's look at a non-software example: file:links-main

java.util.Arrays#sort(T[],%20java.util.Comparator)
java.util.Collections#sort(java.util.List,%20java.util.Comparator)
java.util.Comparator

Function Objects: Command [46/47]

We want allow clients to execute arbitrary code.

Like strategy, but we don't care what the function does.

java.lang.Runnable

Function Objects: Homework 2 [47/47]

See here.

Revised: 2008/09/17 18:24