Liang Chapter 13 — Abstract Classes, Abstract Methods, Interfaces, Comparable, and Abstract Classes vs. Interfaces
Abstract Classes
An abstract class is a class declared with the abstract keyword. It cannot be instantiated directly — you cannot use new on it. It is designed to be a superclass that provides a common template for its subclasses. (Liang, Section 13.2)
The Big Picture
Consider GeometricObject: every shape has an area and perimeter, but there is no such thing as a "generic geometric object" — only circles, rectangles, triangles. So GeometricObject is abstract; its concrete subclasses provide real implementations.
«abstract» GeometricObject
getArea() — abstract getPerimeter() — abstract
Circle
getArea() → π r² getPerimeter() → 2πr
Rectangle
getArea() → w × h getPerimeter() → 2(w+h)
Triangle
getArea() → ½ b × h getPerimeter() → a+b+c
Declaring an Abstract Class
public abstract classGeometricObject {
privateString color = "white";
privateboolean filled;
// Regular (concrete) constructor — abstract classes CAN have constructorsprotectedGeometricObject() {}
protectedGeometricObject(String color, boolean filled) {
this.color = color;
this.filled = filled;
}
// Concrete methods — shared by all subclassespublicStringgetColor() { return color; }
public voidsetColor(String color) { this.color = color; }
publicbooleanisFilled() { return filled; }
// Abstract methods — MUST be implemented by each concrete subclasspublic abstract doublegetArea();
public abstract doublegetPerimeter();
}
// Attempting to instantiate an abstract class → COMPILE ERROR:// GeometricObject g = new GeometricObject(); // ERROR!// A concrete subclass that MUST implement all abstract methods:public classCircleextendsGeometricObject {
private double radius;
publicCircle(double radius) { this.radius = radius; }
@Override
public doublegetArea() { return Math.PI * radius * radius; }
@Override
public doublegetPerimeter() { return2 * Math.PI * radius; }
}
Key Facts About Abstract Classes
Declared with the abstract keyword before class
Cannot be instantiated with new
Can contain both abstract and concrete (regular) methods
Can contain constructors, fields, and static methods
A subclass of an abstract class must implement ALL abstract methods, or else it too must be declared abstract
Abstract Class Variables Are Fine
You cannot create an object of an abstract class, but you can declare a variable of an abstract class type: GeometricObject g = new Circle(5); — this is polymorphism. The variable type is abstract; the actual object is concrete. (Liang, Section 13.2)
Q1: Which statement about abstract classes is TRUE?
A) An abstract class cannot have any concrete methods
B) An abstract class can be instantiated directly with new
C) An abstract class cannot be instantiated but can be used as a variable type
D) An abstract class must have at least one abstract method
Abstract classes cannot be instantiated, but you can declare a variable of that type and assign a concrete subclass object to it. Also note: a class can be declared abstract even with zero abstract methods — though this is unusual. (Liang, Section 13.2)
Q2: A subclass of an abstract class that does NOT implement all abstract methods must be declared as:
A) final
B) abstract
C) interface
D) static
If a subclass does not provide implementations for all inherited abstract methods, it must itself be declared abstract. Otherwise the compiler will report an error. (Liang, Section 13.2)
Section Score
0 / 0
Abstract Methods
An abstract method has a signature but no body — it ends with a semicolon instead of curly braces. It is a contract: every concrete subclass must provide its own implementation. (Liang, Section 13.2)
Abstract Method Syntax
// Inside an abstract class:public abstract doublegetArea(); // No body — ends with semicolonpublic abstract doublegetPerimeter(); // No body — ends with semicolon// A concrete method DOES have a body:publicStringtoString() {
return"color: " + color + ", filled: " + filled;
}
Abstract Method Rules
Rule
Detail
Declared with abstract keyword
No body — ends in ;
Only in abstract classes
A concrete class cannot have abstract methods
Cannot be static
Abstract methods require an object to dispatch on
Cannot be private
Subclasses must be able to override them
Cannot be final
Final methods cannot be overridden — contradiction
Subclass must implement
Or subclass itself must be abstract
Full Example — Abstract → Concrete
public abstract classShape {
public abstract doublegetArea(); // contract — no implementation herepublic voidprintArea() { // concrete method — calls abstract getArea()
System.out.printf("Area = %.2f%n", getArea());
}
}
public classSquareextendsShape {
private double side;
publicSquare(double side) { this.side = side; }
@Override
public doublegetArea() { return side * side; } // MUST implement
}
// In main:
Shape s = newSquare(4);
s.printArea(); // Area = 16.00
Trace: What does this print?
abstract classAnimal {
public abstractStringsound();
public voiddescribe() {
System.out.println("I make the sound: " + sound());
}
}
classDogextendsAnimal {
@Override
publicStringsound() { return"Woof"; }
}
// In main:
Animal a = newDog();
a.describe();
Q1: Which of the following is a valid abstract method declaration?
A) public abstract void display() { }
B) public abstract double getArea();
C) private abstract void show();
D) static abstract int count();
An abstract method has no body (no { }) and ends with a semicolon. It cannot be private (subclasses need access) or static (abstract requires dynamic dispatch). (Liang, Section 13.2)
Q2: Can an abstract class contain concrete (non-abstract) methods?
A) Yes — abstract classes can mix abstract and concrete methods
B) No — every method in an abstract class must be abstract
C) Only if the class has no fields
D) Only static methods can be concrete in an abstract class
Abstract classes can (and often do) contain concrete methods that are shared by all subclasses. Only methods declared abstract must be implemented by subclasses. This is one of the advantages of abstract classes over interfaces. (Liang, Section 13.2)
Section Score
0 / 0
Interfaces
An interface is a contract that specifies what a class must do — but not how. It declares a set of abstract methods (and optionally constants and default methods) that any implementing class must provide. (Liang, Section 13.5)
Defining an Interface
public interfaceEdible {
// All methods are implicitly public and abstractStringhowToEat(); // no body — implementing class must provide one// Constants are implicitly public static finalint MAX_SERVING = 5; // = public static final int MAX_SERVING = 5;
}
public interfaceFlyable {
doublegetMaxAltitude();
doublegetSpeed();
}
Implementing an Interface
// A class implements an interface with the "implements" keywordpublic classChickenimplementsEdible {
@Override
publicStringhowToEat() { return"Fry it"; }
}
// A class can implement MULTIPLE interfaces — Java's answer to multiple inheritancepublic classDuckextendsAnimalimplementsEdible, Flyable {
@Override
publicStringhowToEat() { return"Roast it"; }
@Override
public doublegetMaxAltitude() { return100; }
@Override
public doublegetSpeed() { return30; }
}
Interface Variables (Polymorphism)
// An interface can be used as a type — just like a class
Edible e1 = newChicken();
Edible e2 = newDuck();
System.out.println(e1.howToEat()); // Fry it
System.out.println(e2.howToEat()); // Roast it// instanceof works with interfaces too:
System.out.println(e2 instanceof Flyable); // true — Duck implements Flyable
Interface Implicit Modifiers
All methods in an interface are implicitly public abstract
All fields (constants) are implicitly public static final
Since Java 8: interfaces can have default and static methods with bodies
Since Java 9: interfaces can have private methods (for internal use)
Q1: A class that implements an interface but does not provide all method implementations must be declared:
A) final
B) abstract
C) static
D) interface
Just like with abstract classes, if a class implements an interface but does not implement all required methods, it must be declared abstract. (Liang, Section 13.5)
Q2: In Java, a class can implement:
A) At most one interface
B) At most two interfaces
C) Multiple interfaces
D) No interface if it extends a class
A class can implement any number of interfaces, separated by commas. A class can also extend one class AND implement multiple interfaces simultaneously. (Liang, Section 13.5)
Section Score
0 / 0
The Comparable Interface
The Comparable<T> interface from java.lang defines a single method compareTo that imposes a natural ordering on objects. Implementing it lets your objects be sorted and compared. (Liang, Section 13.6)
The Comparable Contract
// The interface definition (from java.lang):public interfaceComparable<T> {
// Returns: negative if this < o
// 0 if this == o
// positive if this > opublic intcompareTo(T o);
}
// Arrays.sort() uses compareTo() internally
Rectangle[] rects = {
newRectangle(5, 2), // area 10newRectangle(1, 8), // area 8newRectangle(3, 4) // area 12
};
java.util.Arrays.sort(rects); // sorts by area ascending: 8, 10, 12// Works because Rectangle implements Comparable<Rectangle>
Why Comparable Matters
Implementing Comparable integrates your class with Java's entire sorting ecosystem: Arrays.sort(), Collections.sort(), TreeSet, TreeMap, and more all rely on compareTo(). String, Integer, Double — all implement Comparable. (Liang, Section 13.6)
Hint: "apple" comes before "banana" alphabetically, so compareTo returns a negative value.
Q1: compareTo should return what value when this object is greater than the argument?
A) A negative number
B) Zero
C) A positive number
D) true
compareTo returns: negative if this < other, 0 if equal, positive if this > other. This three-way result is what allows sorting algorithms to order objects correctly. (Liang, Section 13.6)
Q2: Which of the following Java classes implements Comparable?
A) Scanner
B) String
C) Random
D) ArrayList
String, Integer, Double, Character, and all wrapper classes implement Comparable. That is why you can sort arrays of strings or integers with Arrays.sort() directly. (Liang, Section 13.6)
Section Score
0 / 0
The Cloneable Interface & Marker Interfaces
A marker interface has no methods — it simply "marks" a class as having a certain capability. Cloneable is the classic example: implementing it signals to the JVM that Object.clone() is allowed for instances of that class. (Liang, Section 13.7)
What Is a Marker Interface?
Key Concept
A marker interface (also called a tagging interface) contains no methods and no constants. Its sole purpose is to attach metadata to a class so the JVM or frameworks can treat it specially at runtime.
java.lang.Cloneable — marks a class as safe to clone
java.io.Serializable — marks a class as safe to serialize
java.util.RandomAccess — marks a List as supporting fast random access
The Cloneable Interface
// java.lang.Cloneable — defined in the JDK:public interfaceCloneable {
// No methods! It is purely a marker.
}
// Without Cloneable, calling clone() throws CloneNotSupportedExceptionpublic classHouseimplementsCloneable {
private int id;
private double area;
publicHouse(int id, double area) {
this.id = id;
this.area = area;
}
// Override clone() from Object and make it public
@Override
public Object clone() {
try {
return super.clone(); // Object.clone() does a shallow copy
} catch (CloneNotSupportedException e) {
return null;
}
}
public String toString() {
return"House[id=" + id + ", area=" + area + "]";
}
}
Cloning in Action
House h1 = newHouse(1, 200.5);
House h2 = (House) h1.clone(); // creates an independent copy
System.out.println(h1); // House[id=1, area=200.5]
System.out.println(h2); // House[id=1, area=200.5]
System.out.println(h1 == h2); // false — different objects
System.out.println(h1.equals(h2)); // false — Object.equals compares refs
Shallow vs. Deep Copy
super.clone() performs a shallow copy: primitive fields are copied by value, but object-reference fields copy the reference (both objects share the same nested object). For a deep copy, you must clone each referenced object yourself inside your clone() method.
Cloneable vs. Comparable — Side by Side
Comparable<T>
Cloneable
Methods defined
compareTo(T o)
none
Purpose
Natural ordering / sorting
Mark as safe to clone
Type
Functional interface
Marker interface
Checked by
Compiler / generics
JVM at runtime
Package
java.lang
java.lang
Q1: What happens if a class does not implement Cloneable but you call clone() on it?
A) The object is cloned using default Java rules
B) A NullPointerException is thrown
C) A CloneNotSupportedException is thrown
D) The compiler rejects the code
Object.clone() checks at runtime whether the class implements Cloneable. If not, it throws CloneNotSupportedException. The compiler will not catch this — it is a runtime check performed by the JVM. (Liang, Section 13.7)
Q2: A marker interface is best described as:
A) An interface with exactly one abstract method
B) An interface with no methods, used to tag a class with metadata
C) An interface that marks default methods
D) An abstract class with no constructors
A marker interface contains no methods and no constants. It exists purely to attach a "tag" to a class that the JVM or frameworks can detect at runtime via instanceof. Cloneable and Serializable are the two most well-known examples in Java.
Section Score: 0 / 0 answered
Abstract Class vs. Interface
Both abstract classes and interfaces define contracts that other classes must fulfill. Choosing between them is one of the most common design decisions in Java OOP. (Liang, Section 13.8)
Side-by-Side Comparison
Feature
Abstract Class
Interface
Keyword
abstract class
interface
Instantiation
Cannot instantiate
Cannot instantiate
Method bodies
Can have concrete methods
All abstract by default (Java 8+: default methods allowed)
Fields
Any type of fields
Only public static final constants
Constructors
Yes — called via super()
No constructors
Access modifiers
Any (public, protected, private)
Methods are implicitly public
Inheritance
A class can extend one abstract class
A class can implement multiple interfaces
Relationship
"is-a" (strong)
"can-do" / "has-ability" (weak)
Use when
Classes share code & state
Unrelated classes share behavior
Design Decision Example
// Use abstract class when classes share CODE and STATE:abstract classVehicle {
protected int speed; // shared statepublic voidaccelerate(int n) { speed += n; } // shared codepublic abstract voidfuelType(); // must differ per subclass
}
// Use interface when UNRELATED classes share a BEHAVIOUR:interfacePrintable {
voidprint(); // A Document, an Invoice, a Photo — all printable, unrelated
}
interfaceSaveable {
voidsave();
}
// A class can do both — extend one class AND implement multiple interfaces:classCarextendsVehicleimplementsPrintable, Saveable {
public voidfuelType() { System.out.println("Gasoline"); }
public voidprint() { System.out.println("Printing car spec..."); }
public voidsave() { System.out.println("Saving car data..."); }
}
The Rule of Thumb
Use an abstract class when the relationship is is-a and subclasses share significant implementation. Use an interface when you want to define a capability (can-do) that may be shared by classes from entirely different hierarchies. When in doubt, prefer interfaces for maximum flexibility. (Liang, Section 13.8)
Common Mistake — Confusing the Two
// WRONG — interface cannot have instance fields:interfaceBad {
int count = 0; // This is actually public static final — not an instance field!voidincrement(); // Cannot change "count" per-object — it's a constant
}
// CORRECT — use an abstract class when you need mutable shared state:abstract classGood {
protected int count = 0; // real instance fieldpublic voidincrement() { count++; }
}
Fields in interfaces are constants — they cannot serve as mutable per-object state. Use an abstract class if you need shared mutable fields.
Q1: Which is true about interfaces vs. abstract classes in terms of inheritance?
A) A class can extend multiple abstract classes
B) A class can implement multiple interfaces but extend only one class
C) A class can implement only one interface
D) Interfaces and abstract classes are identical
Java allows a class to implement any number of interfaces but only extend one class (abstract or concrete). This is why interfaces are used for multiple-inheritance-like behavior. (Liang, Section 13.8)
Q2: You are designing a system where Circle, Rectangle, and Triangle all share common fields (color, filled) and utility methods. You should use:
A) An abstract class — to share state and code
B) An interface — because all three are different shapes
C) A concrete superclass they all extend
D) Three separate unrelated classes
When related classes share both code (methods) and state (fields), an abstract class is the right choice. Interfaces cannot hold instance fields or provide shared field-based behavior. (Liang, Section 13.8)