Was tippt Ente?


428

Ich bin beim Lesen von zufälligen Themen über Software online auf den Begriff Entenschreiben gestoßen und habe ihn nicht vollständig verstanden.

Was ist "Ententyping"?


1
@Mitch Ich habe versucht, etwas als eine Form der Vererbung zu bekommen. Konnte aber nicht viel folgen. Entschuldigung, wenn ich die falsche Frage gestellt habe.
Sushil Bharwani

3
@sushil bharwani: nein, nicht böse. Aber die Leute erwarten, dass als erste Anlaufstelle (dh als erstes, was Sie tun) die Suche versucht wird, bevor Sie hier posten.
Mitch Wheat

104
Angesichts der obigen Argumente scheint es nicht notwendig zu sein, einen Stapelüberlauf durchzuführen, da ich sicher bin, dass fast jede Frage, an die man denken könnte, irgendwo im Internet beantwortet wird, und wenn nicht, könnte die Antwort wahrscheinlich einfacher und ohne Kritik per E-Mail an a erhalten werden sachkundiger Freund. Ich denke, viele von Ihnen haben den Punkt des Stapelüberlaufs verpasst.
Rhody

41
Ich bin sicher, ich habe irgendwo gelesen, dass SO "ein Aufbewahrungsort für kanonische Fragen" sein sollte, und ich bin mir ziemlich sicher, dass Sie nicht kanonischer sein können als diese.
Heltonbiker

Antworten:


302

Es ist ein Begriff, der in dynamischen Sprachen verwendet wird , die keine starke Typisierung aufweisen .

Die Idee ist, dass Sie keinen Typ benötigen, um eine vorhandene Methode für ein Objekt aufzurufen. Wenn eine Methode darauf definiert ist, können Sie sie aufrufen.

Der Name kommt von der Phrase "Wenn es wie eine Ente aussieht und wie eine Ente quakt, ist es eine Ente".

Wikipedia hat viel mehr Informationen.


24
Seien Sie vorsichtig bei der Verwendung von Strong Typing. Es ist nicht so gut definiert. Duck Typing auch nicht. Google Go oder Ocaml sind statisch typisierte Sprachen mit einer strukturellen Subtypisierungskonstruktion. Sind diese Sprachen vom Typ Ente?
Ich gebe Crap Antworten

7
Ein besserer Ausdruck für das Tippen von Enten ist: "Wenn gesagt wird, dass es eine Ente ist ... nun, das ist gut genug für mich." siehe pyvideo.org/video/1669/keynote-3 28:30 oder youtube.com/watch?v=NfngrdLv9ZQ#t=1716
tovmeod

7
Das Entenschreiben wird nicht unbedingt nur in dynamischen Sprachen verwendet. Objective-C ist keine dynamische Sprache und verwendet die Ententypisierung.
Augen

12
Sowohl Python als auch Ruby sind stark typisierte Sprachen und beide haben Duck Typing. String Typing bedeutet nicht, dass Duck Typing nicht vorhanden ist.
Alanjds

8
Ich stimme das ab. Duck Ducking hat nichts mit der Stärke des Typs zu tun, sondern nur mit der Fähigkeit, jedes Objekt mit einer Methode verwenden zu können, ob es eine Schnittstelle implementiert oder nicht.
E-Satis

209

Ententypisierung bedeutet, dass eine Operation die Anforderungen, die ihre Operanden erfüllen müssen, nicht formal spezifiziert , sondern sie nur mit dem Gegebenen ausprobiert.

Anders als andere gesagt haben, bezieht sich dies nicht unbedingt auf dynamische Sprachen oder Vererbungsprobleme.

Beispielaufgabe: Rufen Sie eine Methode Quackfür ein Objekt auf.

Ohne Ententypisierung muss eine Funktion f, die diese Aufgabe ausführt, im Voraus angeben, dass ihr Argument eine Methode unterstützen muss Quack. Ein üblicher Weg ist die Verwendung von Schnittstellen

interface IQuack { 
    void Quack();
}

void f(IQuack x) { 
    x.Quack(); 
}

Der Aufruf f(42)schlägt fehl, f(donald)funktioniert jedoch, solange donaldes sich um eine Instanz eines IQuackUntertyps handelt.

Ein anderer Ansatz ist die strukturelle Typisierung - aber auch hier wird die Methode Quack()formal spezifiziert. Alles, was nicht quackim Voraus beweisen kann , führt zu einem Compilerfehler.

def f(x : { def Quack() : Unit }) = x.Quack() 

Wir könnten sogar schreiben

f :: Quackable a => a -> IO ()
f = quack

in Haskell, wo die QuackableTypklasse die Existenz unserer Methode sicherstellt.


Wie ändert das Tippen von Enten das?

Nun, wie gesagt, ein Enten-Typisierungssystem spezifiziert keine Anforderungen, sondern versucht nur, ob etwas funktioniert .

Daher verwendet ein dynamisches Typsystem wie Pythons immer die Ententypisierung:

def f(x):
    x.Quack()

Wenn fein xunterstützendes a Quack()angezeigt wird, ist alles in Ordnung. Wenn nicht, stürzt es zur Laufzeit ab.

Das Tippen von Enten impliziert jedoch überhaupt kein dynamisches Tippen. Tatsächlich gibt es einen sehr beliebten, aber vollständig statischen Ansatz zum Tippen von Enten, der auch keine Anforderungen stellt:

template <typename T>
void f(T x) { x.Quack(); } 

Die Funktion sagt in keiner Weise, dass sie etwas will x, das kann Quack, also versucht sie stattdessen nur die Kompilierungszeit und wenn alles funktioniert, ist es in Ordnung.


5
meinten Sie nicht: void f (IQuak x) {x.Quak (); } (anstelle von K.Quack), weil der Parameter der Funktion f IQuack x ist, nicht Iquack k, ein sehr kleiner Fehler, aber ich hatte das Gefühl, dass er korrigiert werden musste :)
dominicbri7

Laut Wikipedia ist Ihr letztes Beispiel "strukturelle Typisierung", nicht "Ententypisierung".
Brilliand

Nun, es scheint, dass es eine separate Frage für diese Diskussion gibt: stackoverflow.com/questions/1948069/…
Brilliand

1
Wenn ich also verstehe, was Sie gesagt haben, besteht der Unterschied zwischen einer Sprache, die die Ententypisierung unterstützt, und einer Sprache, die dies nicht tut, darin, dass Sie bei der Ententypisierung nicht den Objekttyp angeben müssen, den eine Funktion akzeptiert? def f(x)statt def f(IQuack x).
PProteus

124

Einfache Erklärung (ohne Code)

Die Diskussion der Semantik der Frage ist ziemlich nuanciert (und sehr akademisch), aber hier ist die allgemeine Idee:

Ententippen

("Wenn es wie eine Ente geht und wie eine Ente quakt, dann ist es eine Ente.") - JA! aber was heißt das ??! Dies lässt sich am besten anhand eines Beispiels veranschaulichen:

Beispiele für Enten-Typisierungsfunktionen:

Stellen Sie sich vor, ich habe einen Zauberstab. Es hat besondere Kräfte. Wenn ich mit dem Zauberstab schwinge und "Drive!" zu einem Auto, na dann fährt es!

Funktioniert es bei anderen Dingen? Ich bin mir nicht sicher: Also versuche ich es auf einem LKW. Wow - es fährt auch! Ich probiere es dann in Flugzeugen, Zügen und 1 Woods aus (sie sind eine Art Golfschläger, mit dem die Leute einen Golfball "fahren"). Sie fahren alle!

Aber würde es beispielsweise bei einer Teetasse funktionieren? Fehler: KAAAA-BOOOOOOM! das hat nicht so gut geklappt. ====> Teetassen können nicht fahren !! duh!?

Dies ist im Grunde das Konzept der Ententypisierung. Es ist ein Try-Before-You-Buy- System. Wenn es funktioniert, ist alles in Ordnung. Aber wenn es fehlschlägt, wie eine Granate, die noch in Ihrer Hand ist, wird es in Ihrem Gesicht explodieren.

Mit anderen Worten, wir interessieren uns eher für das, was das Objekt kann , als für das, was das Objekt ist .

Beispiel: statisch typisierte Sprachen

Wenn wir uns mit dem befassten, was das Objekt tatsächlich war , funktioniert unser Zaubertrick nur bei voreingestellten, autorisierten Typen - in diesem Fall Autos -, aber bei anderen Objekten, die fahren können : Lastwagen, Mopeds, Tuk-Tuks usw. Es funktioniert nicht auf Lastwagen, weil unser Zauberstab erwartet, dass es nur auf Autos funktioniert .

Mit anderen Worten, in diesem Szenario untersucht der Zauberstab sehr genau, was das Objekt ist (ist es ein Auto?), Und nicht, was das Objekt tun kann (z. B. ob Autos, Lastwagen usw. fahren können).

Die einzige Möglichkeit, einen LKW zum Fahren zu bringen, besteht darin, den Zauberstab dazu zu bringen, sowohl LKWs als auch Autos zu erwarten (möglicherweise durch "Implementieren einer gemeinsamen Schnittstelle"). Wenn Sie nicht wissen, was das bedeutet, ignorieren Sie es einfach für den Moment.

Zusammenfassung: Schlüssel zum Mitnehmen

Was beim Entenschreiben wichtig ist, ist, was das Objekt tatsächlich kann und nicht, was das Objekt ist .


Ich finde die Prämisse interessant, dass Sie sich mehr um das Verhalten kümmern, das ist die Definition. Zweifellos ist BDD in Sprachen wie Ruby so erfolgreich.
Pablo Olmos de Aguilera C.

27

Angenommen, Sie entwerfen eine einfache Funktion, die ein Objekt vom Typ Birdabruft und dessen walk()Methode aufruft . Es gibt zwei Ansätze, die Sie sich vorstellen können:

  1. Dies ist meine Funktion und ich muss sicher sein, dass sie nur die akzeptiert Bird, sonst wird ihr Code nicht kompiliert. Wenn jemand meine Funktion nutzen möchte, muss er sich bewusst sein, dass ich nur Birds akzeptiere
  2. Meine Funktion bekommt keine objectsund ich rufe einfach die walk()Methode des Objekts auf . Also, wenn die objectDose walk()es richtig ist, wenn es nicht kann, wird meine Funktion fehlschlagen. Hier ist es also nicht wichtig, dass das Objekt ein Birdoder etwas anderes ist, es ist wichtig, dass es kann walk() (Dies ist Ententypisierung ).

Es muss berücksichtigt werden, dass die Ententypisierung in einigen Fällen nützlich sein kann, zum Beispiel verwendet Python häufig die Ententypisierung .


Nützliches Lesen


1
Schöne Erklärung, was sind irgendwelche Vorteile?
Sushil Bharwani

2
Diese Antwort ist einfach, klar und wahrscheinlich die beste für Anfänger. Lesen Sie diese Antwort zusammen mit der Antwort darüber (oder wenn sie sich bewegt, die Antwort, die über Autos und Teetassen spricht)
DORRITO

18

Wikipedia hat eine ziemlich detaillierte Erklärung:

http://en.wikipedia.org/wiki/Duck_typing

Die Ententypisierung ist eine Art der dynamischen Typisierung, bei der die aktuellen Methoden und Eigenschaften eines Objekts die gültige Semantik bestimmen und nicht die Vererbung von einer bestimmten Klasse oder Implementierung einer bestimmten Schnittstelle.

Der wichtige Hinweis ist wahrscheinlich, dass sich ein Entwickler beim Enten-Tippen mehr mit den Teilen des Objekts befasst, die verbraucht werden, als mit dem tatsächlichen zugrunde liegenden Typ.


13

Ich sehe viele Antworten, die die alte Redewendung wiederholen:

Wenn es wie eine Ente aussieht und wie eine Ente quakt, ist es eine Ente

und dann tauchen Sie ein in eine Erklärung, was Sie mit dem Tippen von Enten tun können, oder in ein Beispiel, das das Konzept weiter zu verschleiern scheint.

Ich finde nicht so viel Hilfe.

Dies ist der beste Versuch, eine einfache englische Antwort über das Tippen von Enten zu finden, die ich gefunden habe:

Ententypisierung bedeutet, dass ein Objekt durch das definiert wird, was es kann, nicht durch das, was es ist.

Dies bedeutet, dass wir uns weniger mit der Klasse / dem Typ eines Objekts befassen als vielmehr damit, welche Methoden darauf aufgerufen werden können und welche Operationen daran ausgeführt werden können. Wir kümmern uns nicht um den Typ, wir kümmern uns darum, was er kann .


3

Ententippen:

Wenn es spricht und geht wie eine Ente, dann ist es eine Ente

Dies wird typischerweise als Entführung bezeichnet ( abduktives Denken oder auch als Rückführung bezeichnet , eine klarere Definition, denke ich):

  • Aus C (Schlussfolgerung, was wir sehen ) und R (Regel, was wir wissen ) akzeptieren / entscheiden / übernehmen wir P (Prämisse, Eigentum ) mit anderen Worten eine gegebene Tatsache an

    ... die Grundlage der medizinischen Diagnose

    mit Enten: C = geht, redet , R = wie eine Ente , P = es ist eine Ente

Zurück zur Programmierung:

  • Objekt o hat Methode / Eigenschaft mp1 und Schnittstelle / Typ T benötigt / definiert mp1

  • Objekt o hat Methode / Eigenschaft mp2 und Schnittstelle / Typ T benötigt / definiert mp2

  • ...

Also mehr als nur akzeptieren mp1 ... für ein Objekt, solange es eine Definition von mp1 ... erfüllt , sollte Compiler / Laufzeit auch mit der Behauptung in Ordnung sein, dass o vom Typ T ist

Und nun, ist es bei den obigen Beispielen der Fall? Ist das Tippen von Enten im Wesentlichen überhaupt kein Tippen? Oder sollten wir es implizite Eingabe nennen?


3

Ein Blick auf die Sprache selbst kann hilfreich sein. es hilft mir oft (ich bin kein englischer Muttersprachler).

Im duck typing :

1) Das Wort typingbedeutet nicht, auf einer Tastatur zu tippen (wie es das beständige Bild in meinem Kopf war), sondern zu bestimmen, " was für ein Ding ist das?" "

2) das Wort duckdrückt aus, wie diese Bestimmung durchgeführt wird; Es ist eine Art "lose" Bestimmung, wie in: " Wenn es wie eine Ente geht ... dann ist es eine Ente ". Es ist "locker", weil das Ding eine Ente sein kann oder nicht, aber ob es tatsächlich eine Ente ist, spielt keine Rolle; Was zählt ist, dass ich damit machen kann, was ich mit Enten machen kann und Verhaltensweisen von Enten erwarte. Ich kann es mit Brotkrumen füttern und das Ding kann auf mich zugehen oder mich angreifen oder sich zurückziehen ... aber es wird mich nicht verschlingen, wie es ein Grizzly tun würde.


2

Ich weiß, dass ich keine allgemeine Antwort gebe. In Ruby deklarieren wir nicht die Arten von Variablen oder Methoden - alles ist nur eine Art Objekt. Die Regel lautet also "Klassen sind keine Typen".

In Ruby ist die Klasse niemals (OK, fast nie) der Typ. Stattdessen wird der Typ eines Objekts mehr durch die Möglichkeiten dieses Objekts definiert. In Ruby nennen wir das Ententippen. Wenn ein Objekt wie eine Ente läuft und wie eine Ente spricht, behandelt der Dolmetscher es gerne so, als wäre es eine Ente.

Beispielsweise schreiben Sie möglicherweise eine Routine, um einer Zeichenfolge Songinformationen hinzuzufügen. Wenn Sie aus einem C # - oder Java-Hintergrund stammen, könnten Sie versucht sein, Folgendes zu schreiben:

def append_song(result, song)
    # test we're given the right parameters 
    unless result.kind_of?(String)
        fail TypeError.new("String expected") end
    unless song.kind_of?(Song)
        fail TypeError.new("Song expected")
end

result << song.title << " (" << song.artist << ")" end
result = ""

append_song(result, song) # => "I Got Rhythm (Gene Kelly)"

Umfassen Sie Rubys Ententipp, und Sie würden etwas viel Einfacheres schreiben:

def append_song(result, song)
    result << song.title << " (" << song.artist << ")"
end

result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"

Sie müssen den Typ der Argumente nicht überprüfen. Wenn sie << (im Fall des Ergebnisses) oder Titel und Künstler (im Fall des Liedes) unterstützen, funktioniert einfach alles. Wenn dies nicht der Fall ist, löst Ihre Methode ohnehin eine Ausnahme aus (genau wie dies der Fall gewesen wäre, wenn Sie die Typen überprüft hätten). Aber ohne die Prüfung ist Ihre Methode plötzlich viel flexibler. Sie könnten ihm ein Array, eine Zeichenfolge, eine Datei oder ein anderes Objekt übergeben, das mit << angehängt wird, und es würde einfach funktionieren.


2

Duck Typing ist kein Type Hinting!

Grundsätzlich verwenden Sie zur Verwendung der "Ententypisierung" nicht einen bestimmten Typ, sondern einen größeren Bereich von Untertypen (ohne Vererbung, wenn ich Untertypen meine, "Dinge", die in dieselben Profile passen), indem Sie eine gemeinsame Schnittstelle verwenden .

Sie können sich ein System vorstellen, das Informationen speichert. Zum Schreiben / Lesen von Informationen benötigen Sie eine Art Speicher und Informationen.

Arten des Speichers können sein: Datei, Datenbank, Sitzung usw.

Die Schnittstelle informiert Sie über die verfügbaren Optionen (Methoden) unabhängig vom Speichertyp, sodass an dieser Stelle nichts implementiert ist! Mit anderen Worten, die Schnittstelle weiß nichts darüber, wie Informationen gespeichert werden.

Jedes Speichersystem muss die Existenz der Schnittstelle kennen, indem es dieselben Methoden implementiert.

interface StorageInterface
{
   public function write(string $key, array $value): bool;
   public function read(string $key): array;
}


class File implements StorageInterface
{
    public function read(string $key): array {
        //reading from a file
    }

    public function write(string $key, array $value): bool {
         //writing in a file implementation
    }
}


class Session implements StorageInterface
{
    public function read(string $key): array {
        //reading from a session
    }

    public function write(string $key, array $value): bool {
         //writing in a session implementation
    }
}


class Storage implements StorageInterface
{
    private $_storage = null;

    function __construct(StorageInterface $storage) {
        $this->_storage = $storage;
    }

    public function read(string $key): array {
        return $this->_storage->read($key);
    }

    public function write(string $key, array $value): bool {
        return ($this->_storage->write($key, $value)) ? true : false;
    }
}

Jedes Mal, wenn Sie Informationen schreiben / lesen müssen:

$file = new Storage(new File());
$file->write('filename', ['information'] );
echo $file->read('filename');

$session = new Storage(new Session());
$session->write('filename', ['information'] );
echo $session->read('filename');

In diesem Beispiel verwenden Sie Duck Typing im Speicherkonstruktor:

function __construct(StorageInterface $storage) ...

Hoffe es hat geholfen;)


2

Baumdurchquerung mit Ententypisierungstechnik

def traverse(t):
    try:
        t.label()
    except AttributeError:
        print(t, end=" ")
    else:
        # Now we know that t.node is defined
        print('(', t.label(), end=" ")
        for child in t:
            traverse(child)
        print(')', end=" ")

0

Ich denke, es ist verwirrt, dynamisches Tippen, statisches Tippen und Ententippen zu verwechseln. Das Tippen von Enten ist ein eigenständiges Konzept, und selbst eine statisch typisierte Sprache wie Go könnte ein Typprüfsystem haben, das das Tippen von Enten implementiert. Wenn ein Typsystem die Methoden eines (deklarierten) Objekts überprüft, jedoch nicht den Typ, kann dies als Entensprachsprache bezeichnet werden.


-1

Ich versuche, den berühmten Satz auf meine Weise zu verstehen: "Python kümmert sich nicht darum, ob ein Objekt eine echte Ente ist oder nicht. Es ist nur wichtig, ob das Objekt, erstens 'Quacksalber', zweitens 'wie eine Ente'."

Es gibt eine gute Website. http://www.voidspace.org.uk/python/articles/duck_typing.shtml#id14

Der Autor wies darauf hin, dass Sie mit der Eingabe von Enten Ihre eigenen Klassen erstellen können, die eine eigene interne Datenstruktur haben - auf die jedoch mit normaler Python-Syntax zugegriffen wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.