Zum Inhalt springen

„Signatur (Programmierung)“ – Versionsunterschied

aus Wikipedia, der freien Enzyklopädie
[ungesichtete Version][gesichtete Version]
Inhalt gelöscht Inhalt hinzugefügt
diverses
===Überladen===-Abschnitt gelöscht. Das wenige sinnvolle, was er enthielt, auf Restartikel verteilt. Und: natürlich kann der Rückgabetyp zur Signatur gehören.
Zeile 1: Zeile 1:
Eine '''Signatur''' (oder '''Methodensignatur''') definiert in der [[Programmierung]] die formale Schnittstelle einer [[Funktion (Programmierung)|Funktion]] oder [[Prozedur (Programmierung)|Prozedur]]. Sie besteht aus dem Namen der Funktion und der Anzahl und Reihenfolge der [[Parameter (Informatik)|Parameterdatentypen]]. Der Rückgabeparametertyp gehört jedoch ''nicht'' zur Signatur (siehe unten).
Eine '''Signatur''' (oder '''Methodensignatur''') definiert in der [[Programmierung]] die formale Schnittstelle einer [[Funktion (Programmierung)|Funktion]] oder [[Prozedur (Programmierung)|Prozedur]]. Sie besteht aus dem Namen der Funktion und der Anzahl und Reihenfolge der [[Parameter (Informatik)|Parameterdatentypen]]. Der Typ des Rückgabewerts gehört gelegentlich ''ebenfalls'' zur Signatur (siehe unten).


Auch die Menge der Operatoren eines [[Abstrakter Datentyp|abstrakten Datentyps]] wird ''Signatur'' genannt.<ref>R. Dumke: ''[http://ivs.cs.uni-magdeburg.de/~dumke/EAD/Skript29.html#adt Einführung, Algorithmen und Datenstrukturen.]'' Otto-von-Guericke-Universität Magdeburg</ref>
Auch die Menge der Operatoren eines [[Abstrakter Datentyp|abstrakten Datentyps]] wird ''Signatur'' genannt.<ref>R. Dumke: ''[http://ivs.cs.uni-magdeburg.de/~dumke/EAD/Skript29.html#adt Einführung, Algorithmen und Datenstrukturen.]'' Otto-von-Guericke-Universität Magdeburg</ref>


== Rückgabeparameter ==
== Rückgabetyp ==
Der Rückgabeparameter gehört nie zur Methodensignatur, weil durch ihn nicht unterschieden werden kann, welche Methode im konkreten Anwendungsfall benutzt werden soll.
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:'''
'''Beispiel:'''
Zeile 15: Zeile 15:
</source>
</source>


Beide Methoden bzw. Funktionen oben hätten die gleiche Signatur.
Beide Methoden bzw. Funktionen oben hätten die gleiche Signatur.


<source lang="java">
<source lang="java">
Zeile 32: Zeile 32:
...
...
</source>
</source>

Im Gegensatz dazu kann die Möglichkeit gegeben werden, in Ausdrücken explizit einen Typ anzugeben. Dadurch kann das Aufrufziel eindeutig angegeben werden. [[Haskell (Programmiersprache)|Haskell]] macht hiervon Gebrauch. Beispielsweise ergeben die Ausdrücke
<source lang="haskell">
read "42" :: Integer
</source>
und
<source lang="haskell">
read "42" :: Double
</source>
verschiedene Werte unterschiedlichen Typs.


== Objektorientierung ==
== Objektorientierung ==
Zeile 82: Zeile 92:


Die Menge aller öffentlichen Signaturen definiert die Schnittstelle einer Klasse.
Die Menge aller öffentlichen Signaturen definiert die Schnittstelle einer Klasse.

=== Überladen von Methoden ===
Soll eine Methode [[überladen]] werden, muss jede Version eine unterschiedliche Signatur besitzen. Dabei wird bei den meisten Programmiersprachen der Rückgabetyp nicht berücksichtigt, weil die andernfalls entstehende Mehrdeutigkeit sowohl die Verständlichkeit des Programms beeinträchtigen als auch den Arbeitsaufwand des [[Compiler]]s deutlich erhöhen würde.


== Interne Repräsentation in Programmiersprachen ==
== Interne Repräsentation in Programmiersprachen ==

Version vom 30. August 2010, 23:52 Uhr

Eine Signatur (oder Methodensignatur) definiert in der Programmierung die formale Schnittstelle einer Funktion oder Prozedur. Sie besteht aus dem Namen der Funktion und der Anzahl und Reihenfolge der Parameterdatentypen. Der Typ des Rückgabewerts gehört gelegentlich ebenfalls zur Signatur (siehe unten).

Auch die Menge der Operatoren eines abstrakten Datentyps wird Signatur genannt.[1]

Rückgabetyp

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:

    ...
     // Deklaration
    float  teile( int dividend, int divisor);    // die Signatur ist hier: teile( int, int )
    double teile (int a, int b);  // nicht erlaubt, Signatur ist dieselbe wie oben: teile( int, int )
    ...

Beide Methoden bzw. Funktionen oben hätten die gleiche Signatur.

     ...
     // Deklaration
     boolean isNegativ( float zahl );   // die Signatur ist isNegativ(float)
     boolean isNegativ( double zahl );  // 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:
    boolean b = 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

    read "42" :: Integer

und

    read "42" :: Double

verschiedene Werte unterschiedlichen Typs.

Objektorientierung

In der objektorientierten Programmierung ist eine Signatur die formale Schnittstelle einer Methode.[2]

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 gleich: Die Methode „String redeMit(String)“ hat in beiden Fällen im Quelltext die Signatur „redeMit(String)“. Die Parameternamen (nicht jedoch Anzahl und Typ) und die Methodeninhalte sind irrelevant. Die Methode in der abgeleiteten Klasse kann somit die Methode der Basisklasse überschreiben. Für den Compiler haben die Methoden jedoch unterschiedliche Signaturen, er berücksichtigt noch die zugehörigen Klassentypen.

Hier ein Beispiel:

// Superklasse
class Person {

    String redeMit( String name ) {
        return "Hallo " + name;
    }       
}

// Instanzen abgeleiteten Klassen können sich auch als Typen ihrer Superklassen ausgeben
class NettePerson extends Person {

    // Methode redeMit(String) wird ueberschrieben
    String redeMit( String name ) {
        return "Schön Dich zu sehen, " + name;
    }
}

public class Main {

    public static void main(String args[]) {

        Person p;

        // hier kann erst zur Laufzeit entschieden werden, welche Methode genommen werden soll
        if ( 0.5 < Math.random() ) {
            p = Person();
        } else {
            p = NettePerson();  // Instanzen vom Typ NettePerson sind auch vom Typ Person, behalten aber ihr "nettes" Verhalten
        }

        for(String name: args)
        System.out.print( p.redeMit( name ) + "." );
    }
}

Der Compiler weiß, dass zu einem Objekt, das von der abgeleiteten Klasse instanziert werden soll, auch die überschriebenen Methoden der abgeleiteten Klasse gehören. Wenn das Objekt dann irgendwo mit Typ seiner Superklasse benutzt wird, wird es aber nur so behandelt, als wäre es vom entsprechenden Superklassentyp. Es werden jedoch die Methoden seiner echten, abgeleiteten Klasse benutzt, die die Superklasse überschrieben haben. Dadurch kann es sich anders verhalten als ein echtes Objekt vom Typ der Superklasse.

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 so genannten dekorierten Funktionsnamen. 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 so genannte method descriptor. Im Gegensatz zu C++ ist diese 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)“.[3]

(IDLjava/lang/Thread;)Ljava/lang/Object;

Quellen

  1. R. Dumke: Einführung, Algorithmen und Datenstrukturen. Otto-von-Guericke-Universität Magdeburg
  2. Rebecca Wirfs-Brock, Brian Wilkerson, Lauren Wiener: Objektorientiertes Software-Design. Carl Hanser Verlag, München 1993, ISBN 3-446-16319-0
  3. Tim Lindholm, Frank Yellin: The JavaTM Virtual Machine Specification: Second Edition. Abschnitt 4.3.3 Method Descriptors.