Vor kurzem hatte ich eine interessante Diskussion im Büro. Wir schauten uns gerade Go an (eine relativ junge Programmiersprache von Google), als das Gespräch auf den Begriff „Polymorphismus“ kam. Erstaunlicherweise gab es mindestens drei unterschiedliche Auffassungen davon, was dieser Begriff bedeutet. Da mein Verständnis des Begriffs „Polymorphismus“ etwas von dem der anderen Beteiligten abwich, möchte ich es hier zur Diskussion stellen. Ich bin gespannt zu hören, welche Meinungen es noch zu dem Thema gibt.
Polymorphismus und Vererbung
Eine häufige verwendete Definition von Polymorphismus ist eng an den Begriff der Vererbung in objektorientierten Programmiersprachen gekoppelt (die folgende Definition ist von der englischen Wikipedia ):
„Subtyping (or inclusion polymorphism) is a concept wherein a name may denote instances of many different classes as long as they are related by some common superclass. In object-oriented programming, this is often referred to simply as polymorphism.“
Dies möchte ich an einem Beispiel erläutern:
1public abstract class Person {
2 abstract String getName();
3}
4
5public class Student extends Person {
6 @Override
7 public String getName() {
8 return "Peter";
9 }
10}
11
12public class Professor extends Person {
13 @Override
14 public String getName() {
15 return "Professor Smith";
16 }
17}
18
19public class App {
20
21 public static void printName(Person person) {
22 System.out.println(person.getName());
23 }
24
25 public static void main(String... args) {
26 Student student = new Student();
27 Professor professor = new Professor();
28
29 printName(student);
30 printName(professor);
31 }
32}
In diesem Beispiel kann der Name person
in der printPerson(Person)
Methode Instanzen von verschiedenen Klassen referenzieren (nämlich von Student
und Professor
). Das Ganze funktioniert, weil beide von Person
ableiten, welche die getName()
Methode definiert. Der Compiler stellt für uns sicher, dass alle Subklassen eine getName()
Methode haben.
Was passiert nun, wenn wir das Beispiel um folgenden Code erweitern:
1public class Dog {
2 public String getName() {
3 return "Pluto";
4 }
5}
Die Dog
Klasse erbt nicht von Person
– ein Hund ist nun mal keine Person. Aber alle Hunde haben für gewöhnlich einen Namen, also macht es Sinn eine getName()
Methode für Hunde zu definieren. Da Java eine statisch typisierte Sprache ist, können wir Instanzen von Dog
nicht an die Methode printName(Person)
übergeben, obwohl Instanzen von Dog
die Schnittstelle anbieten, welche printPerson(Person)
benötigt (nämlich eine Methode mit dem Namen „getName“, die keine Eingangsparameter übernimmt und einen String zurück gibt). Polymorphismus ist in Java also an Vererbung gebunden.
Ein weiteres Problem der obigen Definition des Begriffs „Polymorphismus“ ist, dass diese das Konzept von Klassen voraussetzt. Daraus leitet sich die Frage ab: Gibt es Polymorphismus in JavaScript? Wir haben Polymorphismus auf der Basis von Vererbung zwischen Klassen definiert. Da JavaScript die Bildung von Klassen nicht explizit unterstützt, sieht es so aus, als gäbe es auch kein Polymorphismus in JavaScript.
Polymorphismus ohne Vererbung
An dieser Stelle müssen wir unsere Sicht auf den Begriff „Polymorphismus“ erweitern. Hier ist das obige Beispiel als JavaScript Code:
1var student = {
2 getName: function() {
3 return "Peter";
4 }
5};
6
7var professor = {
8 getName: function() {
9 return "Professor Smith";
10 }
11};
12
13var printName = function(param) {
14 console.log(param.getName());
15};
16
17printName(student);
18printName(professor);
Obowhl es weder Vererbung noch Klassen in JavaScript gibt, sieht es so aus als würde sich die Funktion printName(param)
polymorph verhalten (ja, es gibt prototypische Vererbung in JavaScript, aber wir wollen es nicht komplizierter machen, als notwendig ;-)). Was passiert jetzt also, wenn wir ein Hunde Objekt hinzufügen?
1var dog = {
2 getName: function() {
3 return "Pluto";
4 }
5};
Können wir den Hunde an die printName(param)
Funktion übergeben? Natürlich können wir das, da JavaScript dynamisch typisiert ist. Es würde einfach „Pluto“ ausgegeben werden.
Eine allgemeinere Definition von Polymorphismus
Das zweite Beispiel führt zu einer allgemeineren Definition des Begriffs „Polymorphismus“, die nicht an die Konzepte von Klassen und Vererbung gebunden ist, sondern nur an das Kernkonzept der Objektorientierung: Objekte, welche Nachrichten miteinander austauschen. 1
„Moment mal… Objekte die Nachrichten austauschen?“ werden Sie jetzt vielleicht sagen.
„Aber natürlich!“ antworte ich.
Der folgende Aufruf in Java:
1pers.getName();
kann übersetzt werden in das Senden der Nachricht „bitte gib mir deinen Namen“ an das Objekt, welches von „pers“ referenziert wird. Das Objekt entscheidet dann, ob es die Nachricht beantworten kann. In Java stellt der Compiler sicher, dass wir nur Nachrichten verschicken, die die Empfängerobjekte beantworten können – Code der Methoden aufruft, welche nicht definiert sind, lässt der Compiler nicht zu. In dynamisch typisierten Sprachen können wir jede beliebige Nachricht an unsere Objekte senden, ohne zu wissen ob diese die Nachrichten tatsächlich behandeln können. In unserem Beispiel beantwortet das Objekt die Nachricht, indem es das Ergebnis des Methodenaufrufs von getName()
zurück liefert.
Mein Begriffsverständnis von „Polymoprhismus“ formuliere ich also folgendermaßen:
„Polymorphismus in einem objektorientierten System ist die Fähigkeit unterschiedlicher Objekte auf die selbe Nachricht mit verschiedenen Antworten zu reagieren.“
Nach dieser Definition sendet der Code in der Java Methode printName(Person)
die Nachricht „gib mir deinen Namen“ an den Eingangsparameter. Instanzen von Klassen, die von Person
ableiten, können auf diese Nachricht mit unterschiedlichen Antworten reagieren. Der Compiler stellt dabei sicher, dass alle Objekte, welche an printName(Person)
übergeben werden, die Nachricht auch wirklich behandeln können.
Die JavaScript Funktion printName(param)
auf der anderen Seite sendet ebenfalls die Nachricht „gib mir deinen Namen“ an ihren Eingangsparameter. Anders als in Java gibt es in JavaScript keine statische Typisierung und keinen Compiler, welcher Parametertypen prüft. Dementsprechend wird auch keine gemeinsame Superklasse benötigt. So lange die Objekte, welche der Funktion übergeben werden die Nachricht „gib mir deinen Namen“ behandeln können, funktioniert alles wunderbar. Wird jedoch ein Objekt übergeben, welches die Nachricht nicht behandeln kann, kommt es zu einem Laufzeitfehler.
Die vorgestellte Definition des Begriffs „Polymorphismus“ ist nicht an die Konzepte von Klassen oder Vererbung gebunden. Sie kann auf statisch typisierte Sprachen mit Vererbung wie Java ebenso angewendet werden, wie auf dynamisch typisierte Sprachen wie JavaScript. Mit anderen Worten: Polymorphismus hängt nicht von Vererbung ab! Im Gegenteil, die Tatsache, dass man Polymorphismus in statisch typisierten Sprachen nur zusammen mit Vererbung nutzen kann, ist sogar eine Einschränkung.
Fußnoten
1. Haben Sie sich schonmal gefragt, welche eigentlich die Kernkonzepte der Objektorientierung sind? Fragen Sie ihre Kollegen danach. Ich bin mir sicher, dass Sie sehr verschiedene Antworten erhalten werden. Die Wahrheit ist, dass es keine formale Definition des Begriffs gibt. Ein sehr gute Lektüre zu diesem Thema ist Armstrong DJ (2006) The quarks of object-oriented development in Communications of the ACM 49(2):123–128 – ich kann sie jedem ans Herz legen, der mit objektorientierten Systemen arbeitet.
Weitere Beiträge
von Benedikt Ritter
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Benedikt Ritter
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.