Working with Abstract Classes and Interfaces
1. Defining Abstract Classes
Example: Abstract class
public abstract class Vehicle {
protected String id;
public Vehicle(String id) { this.id = id; }
public abstract double fuelCost(); // no body
public String summary() { return id + ": $" + fuelCost(); }
}
| Feature | Detail |
|---|---|
| Cannot instantiate | Use concrete subclass |
| Can have state | Fields, constructors |
| Mix | Abstract + concrete methods |
2. Creating Abstract Methods
| Rule | Detail |
|---|---|
| No body | End with semicolon |
| Modifier | abstract required |
| Cannot be | static, final, private |
3. Implementing Abstract Classes
| Requirement | Detail |
|---|---|
| Subclass | Must implement all abstract methods OR be abstract |
| Constructor | Subclass calls super constructor |
4. Defining Interfaces
Example: Interface
public interface Repository<T, ID> {
T findById(ID id);
List<T> findAll();
void save(T entity);
default boolean exists(ID id) { return findById(id) != null; }
static Repository<?, ?> empty() { return new EmptyRepo(); }
}
| Member | Implicit Modifiers |
|---|---|
| Field | public static final |
| Abstract method | public abstract |
| Default method | public (Java 8+) |
| Static method | public (Java 8+) |
| Private method | private (Java 9+) |
5. Implementing Interfaces
| Form | Syntax |
|---|---|
| Single | class A implements I { } |
| Multiple | class A implements I1, I2 { } |
| With extends | class A extends B implements I { } |
| Interface extends | interface J extends I1, I2 { } |
6. Using Multiple Inheritance with Interfaces
Warning: If two interfaces declare same default method, subclass MUST override to resolve.
Example: Diamond resolution
interface A { default String hi() { return "A"; } }
interface B { default String hi() { return "B"; } }
class C implements A, B {
@Override public String hi() { return A.super.hi() + B.super.hi(); }
}
| Conflict | Resolution |
|---|---|
| Same default method | Override and use Interface.super.method() |
| Class wins | Concrete method takes priority over default |
7. Defining Default Methods
| Aspect | Detail |
|---|---|
| Purpose | Add behavior without breaking existing implementors |
| Syntax | default ReturnType method() { ... } |
| Override | Subclass may override |
8. Defining Static Methods in Interfaces
| Aspect | Detail |
|---|---|
| Access | InterfaceName.method() |
| Inheritance | NOT inherited by implementors |
| Use | Factory methods, utilities |
9. Defining Private Methods in Interfaces
| Form | Use |
|---|---|
private | Helper for default methods |
private static | Helper for static methods |
10. Understanding Functional Interfaces
Example: Custom @FunctionalInterface
@FunctionalInterface
interface Validator<T> {
boolean isValid(T value);
}
Validator<String> nonEmpty = s -> s != null && !s.isEmpty();
| Rule | Detail |
|---|---|
| Single abstract method (SAM) | Exactly one |
| Default/static methods | Allowed |
Object public methods | Don't count |
| Annotation | @FunctionalInterface enforces SAM |
11. Working with Marker Interfaces
| Marker | Purpose |
|---|---|
Serializable | Marks class as serializable |
Cloneable | Allows Object.clone() |
RandomAccess | Constant-time list access |
Note: Modern alternative — annotations or sealed interfaces with no methods.
12. Understanding Interface vs Abstract Class
| Feature | Interface | Abstract Class |
|---|---|---|
| State (instance fields) | No | Yes |
| Constructors | No | Yes |
| Multiple inheritance | Yes | No |
| Method visibility | public/private only | Any |
| Use case | Capability/contract | Partial impl + state |