Skip to content
IRC-Coding IRC-Coding
Abstraction Interface Abstract Class Design by Contract Open Closed Principle

OOP Abstraction: Interfaces & Design by Contract

Master OOP abstraction: reduce complexity with interfaces, abstract classes, and Design by Contract principles.

S

schutzgeist

2 min read
OOP Abstraction: Interfaces & Design by Contract

OOP Abstraction: Fundamentals, Interfaces & Design by Contract

This article is a definition of terms for abstraction in object-oriented programming – including exam questions and tags.

In a Nutshell

Abstraction reduces complex systems to their essential properties and operations, it defines the what of an interface, the how remains hidden and can be developed independently.

Compact Technical Description

Abstraction is a fundamental concept that reduces complex reality to relevant properties and hides unimportant details. In OOP, abstraction manifests itself through:

  • Interfaces: Pure contract definition without implementation
  • Abstract Classes: Partial implementation with abstract methods
  • Design by Contract: Preconditions, postconditions, invariants

Abstraction enables independent development of implementations, as long as the contract is maintained. It supports the Open Closed Principle: Extensions through new implementations without changing existing code.

Separating the what (interface) from the how (implementation) is the core of good software architecture. Abstraction reduces cognitive load, promotes reusability, and enables flexible, testable systems.

Exam-Relevant Key Points

  • What vs How: Interface defines what, implementation how
  • Interfaces: Pure contract definition, no implementation
  • Abstract Classes: Concrete and abstract methods mixed
  • Design by Contract: Preconditions, postconditions, invariants
  • Open Closed Principle: Extendable without modification
  • Abstraction vs Encapsulation: Abstraction hides complexity, encapsulation protects data
  • Polymorphism: Different implementations of an interface
  • Dependency Inversion: Dependency on abstractions, not concretions

Core Components

  1. Interface: Defines method signatures without implementation
  2. Abstract Class: Can contain partially implemented methods
  3. Concrete Class: Implements all abstract methods
  4. Contract: Guaranteed behavior of the implementation
  5. Preconditions: Requirements for method call
  6. Postconditions: Guarantees after method execution
  7. Invariants: Conditions that must always hold
  8. Dependency Injection: Passing abstractions instead of concretions

Practical Example

// Interface: Defines the contract
interface DatabaseConnection {
    void connect(String url, String user, String password);
    void disconnect();
    ResultSet executeQuery(String sql);
    void executeUpdate(String sql);
}

// Abstract Class: Common functionality
abstract class AbstractDatabase implements DatabaseConnection {
    protected boolean connected = false;
    protected String url;
    
    @Override
    public void connect(String url, String user, String password) {
        if (connected) {
            throw new IllegalStateException("Already connected");
        }
        this.url = url;
        // Check preconditions
        validateConnectionParameters(url, user, password);
        
        // Abstract method implemented by subclasses
        doConnect(url, user, password);
        
        connected = true;
        // Postcondition: Connection must be established
        assert connected : "Connection failed";
    }
    
    @Override
    public void disconnect() {
        if (!connected) {
            throw new IllegalStateException("Not connected");
        }
        doDisconnect();
        connected = false;
    }
    
    // Abstract methods for implementation
    protected abstract void doConnect(String url, String user, String password);
    protected abstract void doDisconnect();
    
    // Common validation
    private void validateConnectionParameters(String url, String user, String password) {
        if (url == null || url.trim().isEmpty()) {
            throw new IllegalArgumentException("URL required");
        }
        if (user == null || user.trim().isEmpty()) {
            throw new IllegalArgumentException("User required");
        }
    }
}

// Concrete implementation
class MySQLDatabase extends AbstractDatabase {
    @Override
    protected void doConnect(String url, String user, String password) {
        System.out.println("MySQL connection is being established to: " + url);
        // MySQL-specific connection establishment
    }
    
    @Override
    protected void doDisconnect() {
        System.out.println("MySQL connection is being disconnected");
        // MySQL-specific disconnection
    }
    
    @Override
    public ResultSet executeQuery(String sql) {
        if (!connected) {
            throw new IllegalStateException("Not connected");
        }
        System.out.println("Execute MySQL query: " + sql);
        return null; // Real ResultSet implementation
    }
    
    @Override
    public void executeUpdate(String sql) {
        if (!connected) {
            throw new IllegalStateException("Not connected");
        }
        System.out.println("Execute MySQL update: " + sql);
    }
}

// Usage with Dependency Injection
class DatabaseService {
    private final DatabaseConnection connection;
    
    // Dependency on abstraction, not concretion
    public DatabaseService(DatabaseConnection connection) {
        this.connection = connection;
    }
    
    public void showData() {
        connection.connect("jdbc:mysql://localhost:3306/db", "user", "pass");
        ResultSet rs = connection.executeQuery("SELECT * FROM customers");
        // Process data...
        connection.disconnect();
    }
}

Advantages and Disadvantages

Advantages

  • Complexity Reduction: Unimportant details hidden
  • Flexibility: Different implementations easily exchangeable
  • Testability: Mocks and stubs easily created
  • Maintainability: Changes in implementation don’t affect interface
  • Teamwork: Parallel development of interface and implementation

Disadvantages

  • Indirection: Additional layer increases complexity
  • Overhead: More code for simple tasks
  • Learning Curve: Abstract thinking requires practice
  • Over-Engineering: Too many abstractions for simple problems

Frequently Asked Exam Questions

  1. What is the difference between abstraction and encapsulation? Abstraction hides complexity (what), encapsulation protects data (how).

  2. When do you use interface vs abstract class? Interface for pure contract definition, abstract class for common implementation.

  3. What is Design by Contract? Definition of preconditions, postconditions, and invariants for software components.

  4. How does abstraction support the Open Closed Principle? Extensions through new implementations without changing existing code.

Most Important Sources

  1. https://en.wikipedia.org/wiki/Abstraction_(computer_science)
  2. https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
  3. https://en.wikipedia.org/wiki/Design_by_contract
Back to Blog
Share:

Related Posts