Eine Signatur (oder Methodensignatur) definiert in der Programmierung die formale Schnittstelle einer Funktion oder Prozedur. Sie besteht aus dem Namen der Funktion sowie der Anzahl, Art und Reihenfolge der zuweisungskompatiblenParameterdatentypen, wobei zwischen Eingangs-, Ausgangs- und Durchgangsparametern unterschieden werden kann. Der Typ des Rückgabewerts gehört bei stark typisierten Programmiersprachen ebenfalls zur Signatur[1][2], genauso wie die Modifikatoren, die die Regeln für die Sichtbarkeit und die Überschreibbarkeit einer Methode festlegen.[3][4]
Unter Signaturvererbung versteht man in der objektorientierten Programmierung die Übertragung einer in der Oberklasse definierten (und eventuell implementierten) Methode auf die Unterklasse. Statische Methoden mit sich unterscheidender Signatur können nicht überschrieben werden, sondern können bei weniger streng strukturierten Programmiersprachen gegebenenfalls überladen werden.
In Pascal- und C-Abkömmlingen und ähnlichen Sprachen, welche bei Überladungen den Rückgabetyp nicht berücksichtigen, kann nicht unterschieden werden, welche Methode im konkreten Anwendungsfall benutzt werden soll.
Beispiel:
...// Deklarationfloatteile(intdividend,intdivisor);// die Signatur ist hier: teile( int, int )doubleteile(inta,intb);// nicht erlaubt, Signatur ist dieselbe wie oben: teile( int, int )...
Beide Methoden bzw. Funktionen oben hätten die gleiche Signatur.
...// DeklarationbooleanisNegativ(floatzahl);// die Signatur ist isNegativ(float)booleanisNegativ(doublezahl);// in Ordnung, Signatur ist anders: isNegativ(double)...
Jetzt könnte nicht mehr entschieden werden, welche Funktion teile (int, int) im konkreten Anwendungsfall benutzt werden soll:
...// Die obigen Funktionen sollen hier benutzt werden:booleanb=isNegativ(teile(x,y));// float teile(..) oder double teile(..) ?...
Im Gegensatz dazu kann die Möglichkeit gegeben werden, in Ausdrücken explizit einen Typ anzugeben. Dadurch kann das Aufrufziel eindeutig angegeben werden. Haskell macht hiervon Gebrauch. Beispielsweise ergeben die Ausdrücke
Signaturen spielen eine Rolle bei der Polymorphie, einem der grundlegenden Konzepte der Objektorientierung. In vielen Programmiersprachen kann eine Methode einer abgeleiteten Klasse die Methode einer Basisklasse genau dann überschreiben, wenn die Signaturen der beiden Methoden identisch sind.
Überschriebene Methoden
Im folgenden Java-Beispiel scheinen die Methodensignaturen aus Oberklasse und abgeleiteter Klasse gleich zu sein: String redeMit( String ). Für den Compiler haben die Methoden jedoch unterschiedliche Signaturen, da er noch die zugehörigen Namensräume und Klassentypen berücksichtigt.
Die Methode der abgeleiteten Klasse hat hier die Methode der Basisklasse überschrieben (englisch override).
Hier ein Beispiel:
// SuperklasseclassPerson{StringredeMit(Stringname){return"Hallo "+name;}}// Abgeleitete Klasse. Superklassenrelation impliziert Supertyprelation.classNettePersonextendsPerson{// Methode redeMit(String) wird überschriebenStringredeMit(Stringname){return"Schön Dich zu sehen, "+name;}}publicclassMain{publicstaticvoidmain(String[]args){Personp;// Hier kann erst zur Laufzeit entschieden werden, welche Methode genommen werden soll.if(0.5<Math.random()){p=newPerson();// originale Person p}else{p=newNettePerson();// Person p wird mit "nettem" Verhalten instanziert.}for(Stringname:args){System.out.println(p.redeMit(name)+".");}}}
Zur Laufzeit führt jedes Objekt einen Zeiger auf eine Tabelle virtueller Methoden mit, die für jede Klasse existiert. Dieser Zeiger wird bei der Objekt-Instanziierung initialisiert und ermöglicht so Polymorphie, also überschreibbares Verhalten.
Unterklasse-Instanzen können gegebenenfalls noch mittels sogenannter Superzeiger auf die überschriebenen Methoden ihrer Superklassen zugreifen.
Klassensignatur
Die Menge aller öffentlichen Signaturen definiert die Schnittstelle einer Klasse.
Interne Repräsentation in Programmiersprachen
Viele C++-Compiler bilden aus dem Namen einer Funktion oder Methode und der kodierten Signatur einen sogenannten dekorierten Funktionsnamen (englischmangled name). Dieser zusammengesetzte Name bildet das Linkersymbol. Damit kann verhindert werden, dass Funktionen mit gleichem Namen, aber unterschiedlicher Signatur durch den Linker fälschlicherweise miteinander verknüpft werden.
Die Namen von Methoden enthalten zusätzlich noch den Klassennamen. Allerdings sind die dekorierten Funktionsnamen nur für den passenden Compiler bzw. Linker zu interpretieren, wie folgendes Beispiel zeigt:
?seekpos@?$basic_streambuf@DU?$char_traits@D@std@@@std@@MAE?AV?$fpos@H@2@V32@H@Z
?seekpos@?$basic_streambuf@GU?$char_traits@G@std@@@std@@MAE?AV?$fpos@H@2@V32@H@Z
In der Programmiersprache Java existiert ebenfalls eine interne Repräsentation von Methodennamen, der sogenannte method descriptor. Im Gegensatz zu C++ ist dieser Teil der Sprachspezifikation und somit für alle Compiler und virtuellen Maschinen identisch. Das folgende Beispiel zeigt die interne Form der Signatur der Methode „Object meineMethode(int i, double d, Thread t)“.[7]