class Horse {

}

class Unicorn extends Horse {

}

Good. More:

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

class Unicorn extends Horse {

}

Welcome to DrJava.  Working directory is C:\Users\dgerman\Desktop
> Unicorn a = new Unicorn();
> a
Unicorn: null
> Horse b = new Unicorn()
> b
Unicorn: null
> Horse c = new Horse()
> c
Horse: null
> a.name = "Adrian";
> a
Unicorn: Adrian


So let me wrap this up:

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.

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

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

This runs thusly:

Welcome to DrJava.  Working directory is C:\Users\dgerman\Desktop
> Unicorn a = new Unicorn("Adrian");
> a
Unicorn: Adrian
> Horse b = new Horse("Seabiscuit");
> b
Horse: Seabiscuit


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.

Answer: (d) 

Let's create some circles, rectangles and triangles.

Let's put them in an array and ask them how big they are. 

I'd like to sort them by area. 

import java.util.*; 

class Example {
  public static void main(String[] args) {
    Circle c = new Circle();
    Triangle t = new Triangle(); 
    Object[] shea = new Object[2]; 
    shea[0] = c;
    shea[1] = t;
    System.out.println( Arrays.toString( shea )); 
    for (Object o : shea)
      System.out.println( o.area() );
  }
}

class Triangle {
  double area() {
    return 2.81;  
  }
}

class Circle {
  double area() {
    return 3.141592;  
  }
}

We need to make a change;


abstract class Shape {
  abstract double area();
}

class Circle extends Shape  {
  double area() {
    return 3.141592;  
  }
}

class Triangle extends Shape {
  double area() {
    return 2.81;  
  }
}

import java.util.*; 

class Example {
  public static void main(String[] args) {
    Circle c = new Circle();
    Triangle t = new Triangle(); 
    Shape[] shea = new Shape[2]; 
    shea[0] = c;
    shea[1] = t;
    System.out.println( Arrays.toString( shea )); 
    for (Shape o : shea)
      System.out.println( o.area() );
  }
}


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.

--