Interfaces and Abstract Classes
## Learning Objectives
- Understand abstract classes
- Create and implement interfaces
- Know when to use each
- Master default and static interface methods
## Abstract Classes
### Cannot Be Instantiated
```java
public abstract class Shape {
String color;
public abstract double area(); // Abstract method
public void display() { // Concrete method
System.out.println("Color: " + color);
}
}
```
### Concrete Subclass
```java
public class Circle extends Shape {
double radius;
public Circle(String color, double radius) {
this.color = color;
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
```
### Usage
```java
// Shape s = new Shape(); // Error - can't instantiate
Shape s = new Circle("Red", 5.0);
System.out.println(s.area()); // 78.54...
```
## Abstract Methods
### No Implementation
```java
public abstract class Animal {
public abstract void makeSound(); // Must be implemented
}
```
### Implementation Required
```java
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow!");
}
}
```
## Interfaces
### Reference: Contract
```java
public interface Drawable {
void draw(); // Abstract by default
}
```
### Implementation: Classes
```java
public class Circle implements Drawable {
@Override
public void draw() {
System.out.println("Drawing circle");
}
}
public class Rectangle implements Drawable {
@Override
public void draw() {
System.out.println("Drawing rectangle");
}
}
```
### Interface Usage
```java
Drawable d = new Circle();
d.draw(); // Drawing circle
d = new Rectangle();
d.draw(); // Drawing rectangle
```
## Interface vs Abstract Class
| Feature | Abstract Class | Interface |
|---------|----------------|----------|
| Fields | Any type | Constants only |
| Methods | Any | Default, static, abstract |
| Constructors | Yes | No |
| Multiple inheritance | No | Yes (multiple interfaces) |
| Access modifiers | Any | public (implicit) |
## Default Methods (Java 8+)
### Provide Implementation
```java
public interface Drawable {
void draw();
default void print() {
System.out.println("Printing...");
}
}
```
### Why Default?
Backward compatibility:
```java
public interface Drawable {
void draw();
// New method with default implementation
default void print() {
System.out.println("Default print");
}
}
// Existing classes don't break - they inherit default
```
## Static Methods in Interfaces
```java
public interface MathUtil {
static int add(int a, int b) {
return a + b;
}
static double circleArea(double radius) {
return Math.PI * radius * radius;
}
}
// Called like: MathUtil.add(5, 3)
```
## Multiple Interfaces
### Class Implements Multiple
```java
public interface Printable {
void print();
}
public interface Drawable {
void draw();
}
public class Document implements Printable, Drawable {
@Override
public void print() {
System.out.println("Printing document");
}
@Override
public void draw() {
System.out.println("Drawing document");
}
}
```
### Interface Extends Interface
```java
public interface Readable extends Printable {
void read();
}
// Class implementing Readable must implement
// both read() (from Readable) and print() (from Printable)
```
## Interface Fields
### Always Constants
```java
public interface Constants {
int MAX_SIZE = 100; // public static final
String DEFAULT_NAME = "Unknown"; // public static final
}
// Usage
int size = Constants.MAX_SIZE;
```
## Functional Interfaces
### Single Abstract Method
```java
@FunctionalInterface
public interface Comparator {
int compare(T o1, T o2);
// equals() is already implemented (from Object)
}
```
### Lambda Expressions
```java
import java.util.Arrays;
import java.util.Comparator;
String[] names = {"Charlie", "Alice", "Bob"};
Arrays.sort(names, (a, b) -> a.compareTo(b));
// or
Arrays.sort(names, Comparator.naturalOrder());
```
## Polymorphism with Interfaces
```java
public interface Shape {
double area();
}
public class Circle implements Shape {
double radius;
@Override
public double area() {
return Math.PI * radius * radius;
}
}
public class Rectangle implements Shape {
double width, height;
@Override
public double area() {
return width * height;
}
}
public static double totalArea(Shape[] shapes) {
double total = 0;
for (Shape s : shapes) {
total += s.area();
}
return total;
}
```
## Private Methods (Java 9+)
### Code Reuse in Interfaces
```java
public interface DataProcessor {
default void process(String data) {
String cleaned = clean(data);
validate(cleaned);
save(cleaned);
}
private String clean(String data) {
return data.trim().toLowerCase();
}
private void validate(String data) {
if (data.isEmpty()) {
throw new IllegalArgumentException("Empty data");
}
}
private void save(String data) {
// save implementation
}
}
```
## Summary
- Abstract classes: partial implementation, single inheritance
- Interfaces: contract only (historically), multiple inheritance
- `abstract class Shape` - use when related classes share state
- `interface Drawable` - use when unrelated classes share behavior
- Default methods provide backwards compatibility
- Interfaces support multiple inheritance
- Functional interfaces can use lambda expressions
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →