Quiz. 

public class Example {
  public static void main(String[] args) {
    Horse a = new Horse("Seabiscuit");  
    System.out.println( a ); 
  }
}

public class Horse {
  private String name; 
  public Horse(String name) {
    this.name = name;  
  }
  public String toString() {
    return "Horse(" + this.name + ")"; 
  } 
}

Now let's create Unicorn. 

This is after some debate: 

public class Horse {
  private String name; 
  public Horse(String name) {
    this.name = name;  
  }
  public String toString() {
    return this.getClass().getName() + "(" + this.name + ")"; 
  } 
}

public class Unicorn extends Horse {
  public Unicorn(String name) {
    // this.name = name; 
    // super.name = name; 
    super(name); 
  } 
}

public class Example {
  public static void main(String[] args) {
    Horse a = new Horse("Seabiscuit");  
    System.out.println( a ); 
    Unicorn b = new Unicorn("Misty"); 
    System.out.println( b ); 
  }
}

This runs as follows: 

Welcome to DrJava.  Working directory is C:\Users\dgerman\Desktop
> run Example
Horse(Seabiscuit)
Unicorn(Misty)


Now the rule we have just experienced is called: 

Constructor Chaining

When you define a class, Java guarantees that the class's constructor method is 
called whenever an instance of that class is created. It also guarantees that the 
constructor is called when an instance of any subclass is created. In order to 
guarantee this second point, Java must ensure that every constructor method calls 
its superclass constructor method. If the first statement in a constructor is not an 
explicit call to a constructor of the superclass with the super keyword, then Java 
implicitly inserts the call super() -- that is, it calls the superclass constructor 
with no arguments. If the superclass does not have a constructor that takes no 
arguments, this causes a compilation error.

There is one exception to the rule that Java invokes super() implicitly if you do 
not do so explicitly. If the first line of a constructor, C1, uses the this() syntax 
to invoke another constructor, C2, of the class, Java relies on C2 to invoke the 
superclass constructor, and does not insert a call to super() into C1. Of course, if 
C2 itself uses this() to invoke a third constructor, C2 does not call super() 
either, but somewhere along the chain, a constructor either explicitly or implicitly 
invokes the superclass constructor, which is what is required.

How did this happen last time? 

class Horse /* extends Object */ {
  Horse () {
    super(); 
  } 
}

class Unicorn extends Horse {
  Unicorn() {
    super(); 
  } 
}

Why did we get stuck today? 

class Horse {
  String name; 
  Horse(String name) {
    super(); // put in by Java 
    this.name = name; 
  }
  Horse() { // this would have "fixed" the issues 

  } 
}

class Unicorn {
  Unicorn() {
    super(); 
  } 
}

Let's look at the lab exercises: 

1. You attempt to compile and run this code:

class Alpha {
  public static void main(String[] args) {
    Beta f = new Beta();
  }
  Alpha(int i) {  }
}

class Beta extends Alpha { }

What is the outcome?

Possible answers:

(a) The code does not compile because Beta does not define a no-args constructor. 
(b) The code does not compile because Beta does not define any constructors whatsoever. 
(c) The code compiles and runs succesfully, with no output. 
(d) The code does not compile because Alpha doesn't define a no-args constructor. 
(e) None of the above.

The correct answer: (d) 

What about abstract classes and interfaces? 

Create an array of circles, triangles and rectangles. 

Go through the array and ask the objects what their area is. 

Abstract Classes and Methods: A Brief Tutorial

 An abstract method has no body, only a signature followed by a semicolon.
For example:

abstract double area(); 
 Any class with an abstract method is automatically abstract itself, and must be declared as such. So we need the blue keyword below, it just has to be there:

abstract class Shape {
  abstract double area(); 
}
 A class may be declared abstract even if it has no abstract methods. This prevents it from being instantiated.

For example:

oldschool.cs.indiana.edu%ls -l
total 1
-rw-------   1 dgerman       134 Jul 16 12:28 Example.java
oldschool.cs.indiana.edu%cat Example.java
abstract class Shape {
  double area() { return -1; } 
  public static void main(String[] args) {
    Shape a = new Shape();  
  } 
}
oldschool.cs.indiana.edu%javac Example.java
Example.java:4: class Shape is an abstract class. It can't be instantiated.
    Shape a = new Shape();  
              ^
1 error
oldschool.cs.indiana.edu%
 An abstract class cannot be instantiated.

This could be seen in the example above.

It can however have a main method with no problem:

oldschool.cs.indiana.edu%ls -l
total 1
-rw-------   1 dgerman       172 Jul 16 12:33 Example.java
oldschool.cs.indiana.edu%cat Example.java
abstract class Shape {
  double area() { return -1; } 
  public static void main(String[] args) {
    System.out.println("Hello!"); 
    // Shape a = new Shape();  
  } 
}
oldschool.cs.indiana.edu%javac Example.java
oldschool.cs.indiana.edu%java Shape
Hello!
oldschool.cs.indiana.edu%
 A subclass of an abstract class can be instantiated if it overrides each of the abstract methods of its superclass and provides an implementation (i.e., a method body) for all of them.

Here's an example that does that and notice the inherited variables too.

oldschool.cs.indiana.edu%ls -l
total 1
-rw-------   1 dgerman       511 Jul 16 12:40 Example.java
oldschool.cs.indiana.edu%cat Example.java
abstract class Shape {
  int x, y; 
  abstract double area(); 
}
 
class Circle extends Shape {
  int radius; 
  double area() { return 2 * Math.PI * radius * radius; }
  double manhattanDistanceToOrigin() {
    return Math.abs(x) + Math.abs(y);  
  }   

 
class Tester {
  public static void main(String[] args) {
    Circle c = new Circle(); 
    c.radius = 10; 
    c.x = -3; c.y = 5; 
    System.out.println("Area is " + c.area() + 
      " and the distance is " + c.manhattanDistanceToOrigin()); 
  } 

oldschool.cs.indiana.edu%javac Example.java
oldschool.cs.indiana.edu%java Tester
Area is 628.3185307179587 and the distance is 8.0
oldschool.cs.indiana.edu%
 If a subclass of an abstract class does not implement all of the abstract methods it inherits, that subclass is itself abstract.
To see this in the code above remove the definition of area() in class Circle and recompile:

oldschool.cs.indiana.edu%ls -l
total 1
-rw-------   1 dgerman       577 Jul 16 12:44 Example.java
oldschool.cs.indiana.edu%cat Example.java
abstract class Shape {
  int x, y; 
  abstract double area(); 
}
 
class Circle extends Shape {
  int radius; 
  /*** let's take area() out, see if it still compiles: 
  double area() { return 2 * Math.PI * radius * radius; }
  ****/ 
  double manhattanDistanceToOrigin() {
    return Math.abs(x) + Math.abs(y);  
  }   

 
class Tester {
  public static void main(String[] args) {
    Circle c = new Circle(); 
    c.radius = 10; 
    c.x = -3; c.y = 5; 
    System.out.println("Area is " + c.area() + 
      " and the distance is " + c.manhattanDistanceToOrigin()); 
  } 

oldschool.cs.indiana.edu%javac Example.java
Example.java:6: class Circle must be declared abstract. It does not define double area() from class Shape.
class Circle extends Shape {
      ^
Example.java:18: class Circle is an abstract class. It can't be instantiated.
    Circle c = new Circle(); 
               ^
2 errors
oldschool.cs.indiana.edu%
It doesn't compile, and for two reasons, not just one.

But the two reasons are closely related.

 I hope you enjoyed this tutorial.

 I strongly hope the information presented in it was quite manageable.

 Please let me know if you have any questions.

class Example {
  public static void main(String[] args) {
    Object[] stuff = new Object[3];
    stuff[0] = new Circle(); 
    stuff[1] = new Triangle(); 
    stuff[2] = new Rectangle(); 
    for (Object o : stuff)
      System.out.println( o );
    
  }
}

class Circle {
  
}

class Rectangle {
  
}

class Triangle {
  
}

Nice but weak. 

class Example {
  public static void main(String[] args) {
    Object[] stuff = new Object[3];
    stuff[0] = new Circle(); 
    stuff[1] = new Triangle(); 
    stuff[2] = new Rectangle(); 
    for (Object o : stuff)
      System.out.println( o.area() );
    
  }
}

class Circle {
  double area() {
    return Math.random();  
  }
}

What do I do? 

class Example {
  public static void main(String[] args) {
    Shape[] stuff = new Shape[3];
    stuff[0] = new Circle(); 
    stuff[1] = new Triangle(); 
    stuff[2] = new Rectangle(); 
    for (Shape o : stuff)
      System.out.println( o.area() );
  }
}

class Shape {
  double area() {
    return Math.random();  
  } 
}

class Circle extends Shape {
  double area() {
    return Math.random();  
  }
}

What's the flaw? 

http://www.cs.indiana.edu/classes/c212/fall2010/notes/abstractclasses.jpg

--