class Shape {

}

class Circle extends Shape {

}

class Rectangle extends Shape {

}

class Example {
  public static void main(String[] args) {
    Shape[] shapes = new Shape[6]; 
    System.out.println( java.util.Arrays.toString( shapes ) ); 
  } 
}

This works and prints [ null, null, null, null, null, null ]

Notice: in a class if you define no constructor Java will define
and provide for you in that class a no-arg default constructor, which
is empty and does nothing. 

I modify Example as follows: 

class Example {
  public static void main(String[] args) {
    Shape[] shapes = new Shape[2]; 
    shapes[0] = new Circle(); // the default no arg constructor in class Circle
    shapes[1] = new Rectangle(); // same reasoning 
    System.out.println( java.util.Arrays.toString( shapes ) ); 
  } 
}

The classes are at this point: 

class Circle extends Shape {
  // there's a default no arg-constructor in this class 
}

class Rectangle extends Shape {
  Rectangle() {
    
  } // with or without this constructor here the code is the same
}

class Shape {



Let's bring Point back:

class Point {
  double x, y;
  Point(double x, double y) {
    this.x = x;
    this.y = y;
  }
}

Let's start making Circle look better: 

class Circle extends Shape {
  Point center; 
  double radius;
  Circle(Point center, double radius) {
    this.center = center;
    this.radius = radius;
  }
  double area() {
    return Math.PI * this.radius * this.radius;  
  }
}


At this point (Shape, Rectangle unchanged) this breaks Example: 

class Example {
  public static void main(String[] args) {
    Shape[] shapes = new Shape[2]; 
    shapes[0] = new Circle(); // the default no arg constructor in class Circle
    // the line above is not acceptable any more 
    shapes[1] = new Rectangle(); // same reasoning 
    System.out.println( java.util.Arrays.toString( shapes ) ); 
  } 
}

Here's the error: 

1 error found:
File: C:\Users\dgerman\Example.java  [line: 4]
Error: C:\Users\dgerman\Example.java:4: cannot find symbol
symbol  : constructor Circle()
location: class Circle

So we lost the default no-arg constructor because we're not defaulting any more. 

class Example {
  public static void main(String[] args) {
    Shape[] shapes = new Shape[2]; 
    shapes[0] = new Circle(new Point(1, 2), 3);
    shapes[1] = new Rectangle(); // same reasoning 
    System.out.println( java.util.Arrays.toString( shapes ) ); 
  } 
}

We had to change Example and now we have no problems again. 

Let's finish Rectangle: 

class Rectangle extends Shape {
  Point center; 
  double width, height;
  Rectangle(Point center, double width, double height) {
    this.center = center; 
    this.width = width;
    this.height = height;
  }
  double area() {
    return this.width * this.height;  
  }
  Rectangle() {
    
  }
}

I am in a slightly different situation now with the constructors...

class Example {
  public static void main(String[] args) {
    Shape[] shapes = new Shape[3]; 
    shapes[0] = new Circle(new Point(1, 2), 3);
    shapes[1] = new Rectangle(); // same reasoning 
    shapes[2] = new Rectangle(new Point(-1, -2), 5, 6);
    System.out.println( java.util.Arrays.toString( shapes ) ); 
    Rectangle r = new Rectangle(); 
    System.out.println( r.center ); // null 
    System.out.println( r.width  ); // 0.0 
    System.out.println( r.height ); // 0.0 
  } 
}

This shows we should think of a default Rectangle.

class Rectangle extends Shape {
  Point center; 
  double width, height;
  Rectangle(Point center, double width, double height) {
    this.center = center; 
    this.width = width;
    this.height = height;
  }
  double area() {
    return this.width * this.height;  
  }
  Rectangle() {
    this.center = new Point(0, 0); 
    this.width = 1; 
    this.height = 1; 
  }
}

So now that's what Example prints.

class Example {
  public static void main(String[] args) {
    Shape[] shapes = new Shape[3]; 
    shapes[0] = new Circle(new Point(1, 2), 3);
    shapes[1] = new Rectangle(); // same reasoning 
    shapes[2] = new Rectangle(new Point(-1, -2), 5, 6);
    System.out.println( java.util.Arrays.toString( shapes ) ); 
    for (int i = 0; i < shapes.length; i++) {
      Shape current = shapes[i]; 
      System.out.println( current.area() );  
    }
    Shape shape = new Shape(); 
    System.out.println( shape.area() ); // though Shape was never meant to be instantiated 
  } 
}

For this to work we had to do this:

class Shape {
  double area() {
    return -1;  
  }
}

But this is embarassing. 

So what options do we have? 

abstract class Shape {
  abstract double area();
}

An abstract class:

  (a) cannot be instantiated
  (b) can have unfinished methods inside (abstract)

class Example {
  public static void main(String[] args) {
    Shape[] shapes = new Shape[3]; 
    shapes[0] = new Circle(new Point(1, 2), 3);
    shapes[1] = new Rectangle(); // same reasoning 
    shapes[2] = new Rectangle(new Point(-1, -2), 5, 6);
    System.out.println( java.util.Arrays.toString( shapes ) ); 
    for (int i = 0; i < shapes.length; i++) {
      Shape current = shapes[i]; 
      System.out.println( current.area() );  
    }
  } 
}

So we can't create Shapes any more. 

We create only Circles and Rectangles. 

And we have another solution too: 

interface Shape {
  double area();
}

class Example {
  public static void main(String[] args) {
    Shape[] shapes = new Shape[3]; 
    shapes[0] = new Circle(new Point(1, 2), 3);
    shapes[1] = new Rectangle(); // same reasoning 
    shapes[2] = new Rectangle(new Point(-1, -2), 5, 6);
    System.out.println( java.util.Arrays.toString( shapes ) ); 
    for (int i = 0; i < shapes.length; i++) {
      Shape current = shapes[i]; 
      System.out.println( current.area() );  
    }
  } 
}

class Circle implements Shape {
  Point center; 
  double radius;
  Circle(Point center, double radius) {
    this.center = center;
    this.radius = radius;
  }
  public double area() {
    return Math.PI * this.radius * this.radius;  
  }
}

class Rectangle implements Shape {
  Point center; 
  double width, height;
  Rectangle(Point center, double width, double height) {
    this.center = center; 
    this.width = width;
    this.height = height;
  }
  public double area() {
    return this.width * this.height;  
  }
  Rectangle() {
    this.center = new Point(0, 0); 
    this.width = 1; 
    this.height = 1; 
  }
}

Everything else (Point) is unchanged. 

Attendance: 

Kexin, Yi, Zhichao, Maxine, Kyle, Ruifeng, 
Yunsheng, Hang, Adam, Adam, Jordan, Yinan, 
Mary Anne, Max, Neelan, Justin, Erik, Chris, 
Alex, Austin, George, Dylan, Lindsay, Stacey, 
Daniel, Justin, Jason, Kyle, Adrian. 

--