Paradigmen der Programmierung

Was ist objektorientierte Programmierung (OOP)?

OOP, Object-Oriented Programming

Objektorientierte Programmierung, kurz OOP, ist ein Programmierparadigma, bei dem Daten und die Funktionen, die mit ihnen arbeiten, in Objekten zusammengefasst werden. Objekte entstehen nach dem Bauplan einer Klasse und arbeiten über ihre Methoden zusammen.

Klassen, Objekte und Vererbung begegnen dir in Java, C#, C++ und Python gleichermaßen, und wer sie einmal richtig sortiert hat, liest fremden Code deutlich schneller.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Vier Begriffe
Kapselung, Abstraktion, Vererbung, Polymorphie
Grundeinheit
Objekt als Instanz einer Klasse
Faustregel
Komposition vor Vererbung
Abgegrenzt von
Prozeduraler und funktionaler Programmierung

Klasse und Objekt

Eine Klasse ist der Bauplan, ein Objekt die einzelne Ausprägung davon zur Laufzeit, auch Instanz genannt. Die Klasse Konto beschreibt, dass es einen Saldo und eine Methode abheben gibt, das Objekt kennt den konkreten Saldo dieses einen Kontos. Die Daten eines Objekts heißen Attribute, seine Funktionen Methoden.

Die Idee stammt aus den 1960er-Jahren: Simula aus Norwegen führte Klassen und Objekte ein, Smalltalk machte das Konzept in den 1970er-Jahren bekannt. Heute sind Java, C#, C++, Python, Kotlin und ABAP Objects objektorientiert, und auch JavaScript arbeitet mit Objekten.

Die vier Grundprinzipien

In Lehrbüchern und Bewerbungsgesprächen tauchen fast immer dieselben vier Prinzipien auf, die zusammen beschreiben, was OOP ausmacht.

  • Kapselung

    Der Zustand eines Objekts ist nur über seine Methoden erreichbar. So setzt die Klasse ihre Regeln selbst durch, etwa dass eine Abhebung den Kreditrahmen nicht überschreitet.

  • Abstraktion

    Nach außen zeigt ein Objekt nur, was es kann, nicht wie es das tut. Wer abheben aufruft, muss nicht wissen, wie der Saldo intern gespeichert ist.

  • Vererbung

    Eine Klasse übernimmt Attribute und Methoden einer anderen und erweitert sie. Ein Sparkonto ist ein Konto, also erbt es von Konto. Vererbung bildet eine Ist-ein-Beziehung ab.

  • Polymorphie

    Derselbe Methodenaufruf führt je nach Objekt zu unterschiedlichem Verhalten. Der aufrufende Code arbeitet gegen die Basisklasse oder ein Interface, welche Umsetzung greift, entscheidet sich zur Laufzeit.

Ein Beispiel in Python

Alle vier Prinzipien passen in wenige Zeilen. Das Beispiel ist in Python geschrieben, in Java oder C# sieht es bis auf die Syntax genauso aus:

class Konto:
    def __init__(self, saldo: float, rahmen: float = 0):
        self._saldo = saldo      # encapsulated state
        self._rahmen = rahmen

    def abheben(self, betrag: float) -> None:
        if betrag > self._saldo + self._rahmen:
            raise ValueError("Rahmen überschritten")
        self._saldo -= betrag

    def monatsabschluss(self) -> None:
        pass


class Sparkonto(Konto):          # inheritance: a Sparkonto is a Konto
    def monatsabschluss(self) -> None:
        self._saldo *= 1.001     # own behaviour for the same call


for konto in [Konto(100), Sparkonto(500)]:
    konto.monatsabschluss()      # polymorphism: caller does not care which type

Die Schleife am Ende ruft für jedes Konto dieselbe Methode auf, und jedes Objekt reagiert auf seine Weise. Kommt später eine dritte Kontoart dazu, ändert sich an der Schleife nichts.

Unterschiede zwischen den Sprachen

Die Sprachen setzen dasselbe Modell unterschiedlich um. Java und C# kennen nur Einfachvererbung, dafür beliebig viele Interfaces, und ein Garbage Collector räumt Objekte weg. In C++ gibt es Mehrfachvererbung, dafür entscheidest du selbst über Lebensdauer und Besitz, üblicherweise über RAII und Smart Pointer. Python erlaubt Mehrfachvererbung und kennt keine echte Zugriffssperre, der Unterstrich vor _saldo ist nur eine Konvention.

Auch die Polymorphie ist unterschiedlich geregelt: In C++ und C# ist ein Methodenaufruf über eine Basisklasse nur dann dynamisch, wenn die Methode als virtual deklariert ist, sonst wird direkt gebunden. Aufrufe über ein C#-Interface sind immer dynamisch. In Java und Python sind Methoden standardmäßig überschreibbar. Wer aus der einen Sprache in die andere wechselt, stolpert meist genau hier.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Nicht verwechseln

Objektorientierte Programmierung und was oft damit gleichgesetzt wird

Objektorientierte Programmierung gegen Prozedurale Programmierung

Dort liegen Daten und Funktionen getrennt, Funktionen bekommen Datenstrukturen übergeben. Bei OOP gehört beides zusammen, und die Art des Objekts bestimmt, welche Umsetzung aufgerufen wird.

Objektorientierte Programmierung gegen Funktionale Programmierung

Sie arbeitet mit unveränderlichen Werten und Funktionen ohne Seiteneffekte, statt Zustand in Objekten zu halten. Moderne Sprachen mischen beides, C# etwa mit Records und LINQ, Java mit Streams.

Objektorientierte Programmierung gegen Prototypbasierte Objektorientierung

JavaScript kam ursprünglich ohne Klassen aus, Objekte erben dort direkt von anderen Objekten, ihren Prototypen. Das Schlüsselwort class ist nachträglich hinzugekommen und baut auf diesem Mechanismus auf.

In der Praxis

Vererbung ist die Bindung, die du am schwersten wieder loswirst

Eine Klasse, die von einer anderen erbt, hängt an deren Innenleben. Ändert die Basisklasse ihr Verhalten, ändern sich alle Nachfahren mit, und in einer Hierarchie über fünf Ebenen findest du die Stelle, an der eine Methode tatsächlich definiert ist, nur noch über die Sprungfunktion der Entwicklungsumgebung. Der klassische Fehler ist, Vererbung zur Wiederverwendung von Code zu benutzen statt für Austauschbarkeit.

Die Alternative heißt Komposition: Die Klasse enthält ein Objekt, das die gewünschte Fähigkeit hat, und reicht Aufrufe weiter. Das kostet mehr Tipparbeit, bleibt dafür beweglicher, weil sich der Bestandteil austauschen lässt. Daher die Faustregel „Komposition vor Vererbung“.

Wenn du doch erbst, halte das Versprechen der Basisklasse. Beantwortet eine abgeleitete Klasse eine geerbte Methode mit einer Ausnahme, weil dieser Fall bei ihr nicht vorgesehen ist, bricht jeder Code, der mit der Basisklasse arbeitet. Vererbung sagt zu, dass das Neue überall dort einsetzbar ist, wo bisher das Alte stand. Diese Regel ist als Liskovsches Substitutionsprinzip das „L“ in SOLID.

Objektorientierte Programmierung lernen

Wie sich Klassen, Interfaces und Speicherverwaltung in beiden Sprachen konkret unterscheiden, arbeiten die Trainings zu C# und C++ nebeneinander durch.

Wer das Paradigma erst einmal unabhängig von einer Sprache verstehen will, ist in den sprachübergreifenden Programmierkursen richtig.

Häufige Fragen

Was heißt OOP?
OOP steht für objektorientierte Programmierung, englisch Object-Oriented Programming. Gemeint ist eine Art, Programme zu strukturieren, nicht eine bestimmte Sprache.
Sind Getter und Setter für jedes Feld guter Stil?
Selten. Wenn zu jedem Feld ein Paar existiert, ist das Objekt nur eine Datenstruktur mit Zeremonie, und von Kapselung bleibt nichts übrig. Besser sind Methoden, die einen fachlichen Vorgang ausdrücken, also einzahlen statt setzeSaldo. Für reine Datenträger gibt es Records in C# und Java oder Dataclasses in Python.
Wann nehme ich ein Interface, wann eine abstrakte Klasse?
Ein Interface beschreibt eine Fähigkeit ohne Zustand und lässt sich beliebig oft ergänzen. Eine abstrakte Klasse bietet gemeinsamen Code und geteilten Zustand, verbraucht in Java und C# aber die eine Basisklasse, die du hast.
Ist OOP überholt?
Nein, aber der Alleinvertretungsanspruch ist weg. Gängige Codebasen mischen: Objekte für langlebigen Zustand und Fachregeln, funktionale Stilmittel für Datentransformationen. Beides in einer Datei ist heute normal und kein Bruch.
Persönlich für dich da

Deine Ansprechpartner

Du willst das Thema nicht nur nachschlagen, sondern anwenden können? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Ordnet mit dir ein, welcher Kurs zu deinem Vorwissen passt.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant Inhouse-Trainings, die an euren eigenen Daten und Abläufen ansetzen.

Objektorientierte Programmierung im Kurs statt im Lexikon

Nachschlagen bringt dich bis zum Verstehen. Anwenden lernst du an echten Aufgaben.