class abstraction


Summary

Abstract classes/methods

  • “is-a” relationship - Circle is a Shape
  • cannont be instantiated
  • can have both concrete fields and methods, and abstract methods
  • abstract methods are left to the child class to implement
java
abstract class A {
	private int a; // concrete field

	public void funcA () { ... // comvrete method and implementation

	public abstract int funcB(); // abstract method, declared but not implemented
}

class B extends A { // has to implement all the methods declared in the parent
	@Override
	public abstract int funcB() { ... // implementation of the abstract method
}

Interfaces

  • “can-do” relationship - Circle can do get area
  • *-able
  • nothing concrete, except fields
  • methods are public by default, ie. must be overridden with explicitly declared public methods
java
interface C {
	void funcC(); // abstract method, is public abstract by default
}

interface D {
	double funcD(); // abstract method
}

class E extends A implements C, D { // only can extend one parent class, but can implement multiple interfaces
	@Override
	public int funcB() { ...
    
	@Override
	public void funcC() { ...
	
	@Override
	public double funcD() { ...
}

a type can have multiple direct supertypes

abstractclass_interfaces.png

Concept

Why?

  • grouping subclasses into categories
  • denoting that a class has a certain feature

Casting to interfaces

  • a class can be cast to any interface, even if it does not implement it
  • compiler trusts the programmer and does not give any warnings
java
interface I {
	...
}

class A {
	...
}

class B implements I {
	...
}

I i1 = new B();     // widening type conversion
I i2 = (I) new A(); // allowed despite A </: I

the java compiler prevents the type cast when its provable that it will not work, as in casting between classes
for interfaces, its possible that a subclass implements the interface

java
class AI extends A implements I {
	...
}

Impure interfaces

  • interface can provide a default implementation of methods
  • classes that implement the impure interfaces will use the default implementation, unless they override the method
  • compatibility with evolving code
java
interface I {
	default void show() { // default implementation, acts as the declaration as well
		System.out.println("Default");
	}
}

class A implements I { // need not override
}

class B implements I {
	@Override
	void show() {
		System.out.println("Overridden");
	}
}

new A().show(); // => "Default"
new B().show(); // => "Overridden"

java 8+

Application

Compile-time type checking

java
public interface Shape {
	public double getArea();
}

public interface Printable {
	public void print();
}

class Circle implements Shape, Printable { // can implement more than one interface
	...
}

Circle c = new Circle(new Point(0,0), 10);
Shape s = c;
Printable p = c;

s.print(); // Fails: Shape doesn't have print()
p.print(); // Works
s.getArea(); // Works
p.getArea(); // Fails: Printable doesn't have getArea()