• Inheritance

### Guess who's inheriting the money

 Lecture notes Inheritance Create comment

### Biology and inheritance

 Lecture notes Inheritance Create comment

### Duplicate code

 public class Rectangle{ // Center coordinate private double x; ❶ private double y; public void move (double dx, double dy){ ❷ x += dx; y += dy; } private double width, height; ❸ ... } public class Circle { // Center coordinate private double x; ❶ private double y; public void move (double dx, double dy){ ❷ x += dx; y += dy; } private double radius; ❸ ... }
 Lecture notes Inheritance Create comment

### Idea: Centralize common code

• Create a parent class Shape containing common code portions.

• Relate both Rectangle and Circle to Shape.

 Lecture notes Inheritance Create comment

### Common and specific properties

Common Rectangle and Circle attributes:
double x;
double y;
Rectangle attributes Circle attributes
double width;
double height;
double radius;
 Lecture notes Inheritance Create comment

### Basic shape inheritance

 Lecture notes Inheritance Create comment

### Basic shape inheritance

 Lecture notes Inheritance Create comment

### Inheritance

• Derived classes inherit state and behaviour.

• Refinement, specialization.

• is-A relationship:

• A rectangle is a shape.

• A circle is a shape.

 Lecture notes Inheritance Create comment

### Implementing Shape hierarchy

 public class Shape { private double x, y; } public class Rectangle extends Shape { private double width; private double height; } public class Circle extends Shape { private double radius; }
 Lecture notes Inheritance Create comment

### Creating instances

final double x = 2, y = 3;
final Shape shape = new Shape(x, y);

final double width = 2, height = 5;
final Rectangle r = new Rectangle(x, y , width, height);

final Circle circle = new Circle(x, y , radius);
 Lecture notes Inheritance Create comment

### Shape constructor

/**
* Creating a shape located at center coordinate.
* @param x The center's x component.
* @param y The center's y component.
*/
public Shape(double x,double y) {
this.x = x;
this.y = y;
}
 Lecture notes Inheritance Create comment

### Creating Rectangle instances

final Rectangle r =
new Rectangle(x, y ❶,
width, height ❷);
 Center coordinate components “belonging” to superclass Shape. width and height “belonging” to class Rectangle.

Solution: Nested constructor call. Coming soon ...

 Lecture notes Inheritance Create comment

### Rectangle constructor

/**
* Creating a rectangle at (x|y) of given width and height.
* @param x Center's x component.
* @param y Center's y component.
* @param width Rectangle's width.
* @param height Rectangle's height.
*/
public Rectangle(double x, double y,
double width, double height) {
super(x, y) ❶;
this.width = width; this.height = height ❷;
}
 Lecture notes Inheritance Create comment

### Overview

• Inheritance
• ➟ Overriding equals() and hashCode()

### Shape.equals()

public abstract class Shape {
...
@Override ❶ public boolean equals(final Object o) {
if (o instanceof Shape ❷) {
final Shape other = (Shape) o; ❸
return x == other.x && y == other.y; ❹
} else {
return false; ❺
} ...
 Lecture notes Inheritance ➟ Overriding equals() and hashCode() Create comment

### Rectangle.equals()

public class Rectangle extends Shape {
...
@Override public boolean equals(final Object o) {
if (o instanceof Rectangle) {
final Rectangle other = (Rectangle) o;
return super.equals(o) ❶ &&  width == other.width && height == other.height ❷;
} else {
return false;
} ...
 Lecture notes Inheritance ➟ Overriding equals() and hashCode() Create comment

### Overview

• Inheritance
• ➟ Overriding toString()

### Shape log info

public class Run {
static final Logger log = LogManager.getLogger(Run.class);
public static void main(String[] args) {
final double x = 2.0, y = 3.0;
final Shape shape = new Shape(x, y);
log.info(shape);  ...
2017... INFO  [main] inherit.Run ... - inherit.Shape@37d31475

Desired:

2017... INFO  [main] inherit.Run ... - (2.0|3.0)
 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Overwriting toString()

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Overwriting toString()

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Overwriting toString()

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Overwriting toString()

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Overwriting toString()

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Shape extending Object

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Shape extending Object

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Shape extending Object

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Logging Rectangle instances

public class Run {
static final Logger log = LogManager.getLogger(Run.class);
public static void main(String[] args) {
final double x = 2, y = 3, width = 3., height = 4.;
final Rectangle r = new Rectangle(x, y, width, height);
log.info(r); ...
2017 ... INFO  [main] inherit.Run (Run.java:15) - (2.0|3.0)

Desired:

2017 ... INFO  Rectangle at (2.0|3.0), width= 3.0, height=4.0
 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Override toString() again.

public class Rectangle extends Shape {
@Override public String toString() {
return "Rectangle at " + super.toString() ❶ +
", width= " + width + ", height=" + height; ❷
} ...
 The super keyword allows for calling the toString() method from superclass Shape. Append class Rectangle's “own” width and height attributes.
 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Rectangle extending Shape

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Rectangle extending Shape

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Rectangle extending Shape

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Rectangle extending Shape

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Implementing Circle.toString()

public class Circle extends Shape {
/**
* Creating a circle of given center and radius
* @param x Center's x component.
* @param y Center's y component.
*/
public Circle(double x,double y, double radius) {
super(x, y);
}
@Override public String toString() {
}
}
 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Shape and toString()

 Lecture notes Inheritance ➟ Overriding toString() Create comment

### Overview

• Inheritance
• ➟ final methods

### Moving Shape instances

 Lecture notes Inheritance ➟ final methods Create comment

### Moving Shape instances

 Lecture notes Inheritance ➟ final methods Create comment

### Moving Shape instances

 Lecture notes Inheritance ➟ final methods Create comment

### Implementing Shape movements

public class Shape {
/**
* Move by a given translation vector
* @param xTrans Translation's x component
* @param yTrans Translation's y component
*/
public void move(final int xTrans, final int yTrans) {
x += xTrans;
y += yTrans;
} ...
 Lecture notes Inheritance ➟ final methods Create comment

### Fools are everywhere!

public class Rectangle extends Shape {
@Override public void move(int xTrans, int yTrans) {
// I'm so dumb!
...
}
 Lecture notes Inheritance ➟ final methods Create comment

### Solution: final prevents overriding

public abstract class Shape {
... public final void move(final int xTrans, final int yTrans) {
x += xTrans;
y += yTrans;
}...
public class Rectangle extends Shape {
// Syntax error: 'move(int, int)' cannot override
// 'move(int, int)' in 'inherit.Shape'; overridden method is final
@Override public void move(int xTrans, int yTrans) {...
 Lecture notes Inheritance ➟ final methods Create comment

### Overview

• Inheritance
• ➟ Abstract methods

### Calculating a shape's area

 public class Rectangle extents Shape { /** * Calculate the area. * @return The rectangle's area */ public double getArea() { return width * height; } public class Circle extents Shape { /** * Calculate the area. * @return The circle's area */ public double getArea() { return Math.PI * radius * radius; }
 Lecture notes Inheritance ➟ Abstract methods Create comment

### Desired: Polymorphic getArea() call

final Shape[] shapes ❶ = {
new Circle(1, 1, 2.) ❷,
new Rectangle(1, -1, 2., 3.)❷};

for (final Shape s : shapes) {
System.out.println(s.toString() + ": area = " + s.getArea()); ❸
}
Circle at (1.0|1.0), radius= 2.0: area = 12.566370614359172
Rectangle at (1.0|-1.0), width= 2.0, height=3.0: area = 6.0
 Lecture notes Inheritance ➟ Abstract methods Create comment

### Problems:

• No meaningful getArea() method in class Shape possible.

• Meaningful implementations exist both in subclass Rectangle and Circle.

Solution: Abstract method getArea() in superclass Shape.

 Lecture notes Inheritance ➟ Abstract methods Create comment

### abstract method getArea()

 abstract❶ public class Shape { /** * Calculate the shape's area. * @return The shape's area */ abstract❷ public double getArea()❸; ... public class Rectangle extends Shape { @Override❶ public double getArea() { return width * height; }... public class Circle ... { @Override❶ public double getArea() { return Math.PI * radius * radius; } ...
 Lecture notes Inheritance ➟ Abstract methods Create comment

### abstract method getArea()

 Lecture notes Inheritance ➟ Abstract methods Create comment

### abstract method getArea()

 Lecture notes Inheritance ➟ Abstract methods Create comment

### abstract method getArea()

 Lecture notes Inheritance ➟ Abstract methods Create comment

### abstract method getArea()

 Lecture notes Inheritance ➟ Abstract methods Create comment

### abstract method getArea()

 Lecture notes Inheritance ➟ Abstract methods Create comment

### abstract method getArea()

 Lecture notes Inheritance ➟ Abstract methods Create comment

### abstract method getArea()

 Lecture notes Inheritance ➟ Abstract methods Create comment

### What's a “shape” anyway?

 Lecture notes Inheritance ➟ Abstract methods Create comment

### No instances of abstract classes.

final Shape s =
new Shape(1., 2.); // 'Shape' is abstract; cannot be instantiated
 Lecture notes Inheritance ➟ Abstract methods Create comment

### Mandatory getArea() implementation.

// Error: Class 'Circle' must either be declared abstract or
//        implement abstract method 'getArea()' in 'Shape'
public class Circle extends Shape {

public Circle(double x,double y, double radius) {
super(x, y);
}
}
 Lecture notes Inheritance ➟ Abstract methods Create comment

### Facts about abstract fields, methods and classes.

• A class containing an abstract method must itself be declared abstract.

• abstract classes are allowed to host non-abstract methods.

• A class may be declared abstract irrespective of purely containing non-abstract methods.

 Lecture notes Inheritance ➟ Abstract methods Create comment

### Overview

• Inheritance
• ➟ Abstract methods
• ➟ Geometry classes reconsidered

### Moving shapes

 Lecture notes Inheritance ➟ Abstract methods ➟ Geometry classes reconsidered Create comment

### Overview

• Inheritance
• ➟ protected access

### protected access

package model;
public abstract class Shape ❶{

final protected long creationTime ❷= System.nanoTime();
...
}
------------------------------------------------
package model.sub;
public class Rectangle ❸extends Shape {
static final Logger log = LogManager.getLogger(Rectangle.class);

@Override public double getArea() {
log.info("Rectangle creation time:" + creationTime ❹);
return width * height;
} ...
}
 Lecture notes Inheritance ➟ protected access Create comment

### Overview

• Inheritance
• ➟ final classes

### final classes

public final class Shape { ... }

-------------------------
public class Rectangle
extends Shape { // Error: final class cannot be extended
...
 Lecture notes Inheritance ➟ final classes Create comment

### final classes, rationale

• Design decision.

• Slight performance gain.

### Note

Prominent Example: java.lang.String.

 Lecture notes Inheritance ➟ final classes Create comment

### Overview

• Inheritance
• ➟ The instanceof operator

### “Defeating” polymorphism

 public static void main(String[] args) { final Shape[] shapes = { new Circle(1, 1, 2.), new Rectangle(1, -1, 2., 3.)}; print(shapes); } static void print(final Shape[] shapes) { for (final Shape s : shapes) { if (s instanceof Rectangle) { System.out.println("Type Rectangle"); } else if (s instanceof Circle) { System.out.println("Type Circle"); } } } Type Circle Type Rectangle
 Lecture notes Inheritance ➟ The instanceof operator Create comment

### Defining equals(...): Expectations

Rectangle r1 = new Rectangle(1, 2, 5, 4),
r2 = new Rectangle(1, 2, 1, 7),
r3 = new Rectangle(1, 2, 5, 4);

Circle c = new Circle(-2, 3, 5);

System.out.println(r1.equals("Hello")); // false: Differing classes Rectangle and String.
System.out.println(r1.equals(r2));      // false: Differing width and height.
System.out.println(r3.equals(r1));      // true:  Two rectangles,
// identical (x|y), width and height.
System.out.println(r1.equals(c));  // false: Differing classes Rectangle and Circle.
System.out.println(c.equals(c));   // true: Object equal to itself.
 Lecture notes Inheritance ➟ The instanceof operator Create comment

### Defining equals(...) of Shape instances

Two Shape instances shall be considered equal if:

• Both instances are of common type i.e. either Rectangle or Circle.

• Their center coordinates match within a threshold of $math formula$.

• width and height or radius match within a threshold of $math formula$.

 Lecture notes Inheritance ➟ The instanceof operator Create comment

### Comparing center coordinates

public abstract class Shape {
private double x, y;

protected boolean equalCenter(final Shape o) {
return Math.abs(o.x - x) + Math.abs(o.y - y) < 1.E-15;
}
...
 Lecture notes Inheritance ➟ The instanceof operator Create comment

### Implementing Rectangle.equals()

public class Rectangle extends Shape {
@Override public boolean equals(Object o) {
if (o instanceof Rectangle){
final Rectangle oRectangle = (Rectangle) o;
return super.equalCenter(oRectangle) &&
Math.abs(oRectangle.width- width) +
Math.abs(oRectangle.height- height) < 1.E-15;
}
return false;
}
...

if o == null then o instanceof Rectangle evaluates to false.

 Lecture notes Inheritance ➟ The instanceof operator Create comment

### Implementing Circle.equals()

public class Circle extends Shape {
@Override public boolean equals(final Object o) {
if (o instanceof Circle){
final Circle oCircle = (Circle) o;
return super.equalCenter(o) &&
}
return false;
} ...
 Lecture notes Inheritance ➟ The instanceof operator Create comment

### Testing equality of Shape objects

 final Rectangle r1 = new Rectangle(2, 3, 1,4), r2 = new Rectangle(2, 3, 2,8), r3 = new Rectangle(2, 3, 1,4); final Circle c = new Circle(2,3, 7); System.out.println("r1.equals(r2): " + r1.equals(r2)); System.out.println("r1.equals(r3): " + r1.equals(r3)); System.out.println("c.equals(r1): " + c.equals(r1)); r1.equals(r2): false r1.equals(r3): true c.equals(r1): false
 Lecture notes Inheritance ➟ The instanceof operator Create comment

### Overview

• Inheritance
• ➟ The @Override annotation.

### Overriding Object.toString()

public class Shape {

double x, y;
...
@Override  // Promise: Subsequent method overrides Object.toString();
public String toString() {
return "(" + x + "|" + y + ")";
}
}
 Lecture notes Inheritance ➟ The @Override annotation. Create comment

### Failure: Not overriding Object.toString()

public class Shape {

double x, y;
...
@Override  // Error: method does not override a method from a supertype
public String toString(int value) {
return "(" + x + "|" + y + ")";
}
}
 Lecture notes Inheritance ➟ The @Override annotation. Create comment