Mi sono imbattuto nel termine digitando anatra mentre leggevo argomenti casuali su software online e non l'ho capito del tutto.
Che cos'è la "tipizzazione anatra"?
Mi sono imbattuto nel termine digitando anatra mentre leggevo argomenti casuali su software online e non l'ho capito del tutto.
Che cos'è la "tipizzazione anatra"?
Risposte:
È un termine usato in linguaggi dinamici che non hanno una digitazione forte .
L'idea è che non è necessario un tipo per invocare un metodo esistente su un oggetto: se un metodo è definito su di esso, è possibile invocarlo.
Il nome deriva dalla frase "Se sembra un'anatra e ciondola come un'anatra, è un'anatra".
Wikipedia ha molte più informazioni.
La tipizzazione anatra significa che un'operazione non specifica formalmente i requisiti che i suoi operandi devono soddisfare, ma lo prova semplicemente con ciò che viene dato.
A differenza di ciò che altri hanno detto, ciò non si riferisce necessariamente a linguaggi dinamici o problemi di eredità.
Attività di esempio: chiamare un metodo Quack
su un oggetto.
Senza utilizzare la digitazione anatra, una funzione che f
esegue questa attività deve specificare in anticipo che il suo argomento deve supportare un metodo Quack
. Un modo comune è l'uso di interfacce
interface IQuack {
void Quack();
}
void f(IQuack x) {
x.Quack();
}
La chiamata ha f(42)
esito negativo, ma f(donald)
funziona fintanto che donald
è un'istanza di un IQuack
sottotipo.
Un altro approccio è la tipizzazione strutturale - ma ancora una volta, il metodo Quack()
è formalmente specificato qualsiasi cosa che non possa dimostrarlo quack
in anticipo causerà un errore del compilatore.
def f(x : { def Quack() : Unit }) = x.Quack()
Potremmo persino scrivere
f :: Quackable a => a -> IO ()
f = quack
in Haskell, dove la Quackable
typeclass garantisce l'esistenza del nostro metodo.
Bene, come ho detto, un sistema di tipizzazione anatra non specifica i requisiti, ma cerca solo se qualcosa funziona .
Pertanto, un sistema di tipo dinamico come quello di Python utilizza sempre la tipizzazione duck:
def f(x):
x.Quack()
Se f
ottiene un x
supporto a Quack()
, tutto va bene, altrimenti si bloccherà in fase di esecuzione.
Ma la tipizzazione anatra non implica affatto la tipizzazione dinamica - in effetti, esiste un approccio molto popolare ma completamente statico alla tipizzazione anatra che non presenta alcun requisito:
template <typename T>
void f(T x) { x.Quack(); }
La funzione non dice in alcun modo che vuole qualcosa x
che può Quack
, quindi invece cerca solo in fase di compilazione e se tutto funziona, va bene.
def f(x)
invece di def f(IQuack x)
.
La discussione sulla semantica della domanda è abbastanza sfumata (e molto accademica), ma ecco l'idea generale:
Duck Typing
("Se cammina come un'anatra e ciondola come un'anatra, allora è un'anatra.") - SÌ! ma cosa significa ??! Questo è meglio illustrato dall'esempio:
Esempi di funzionalità di digitazione anatra:
Immagina di avere una bacchetta magica. Ha poteri speciali. Se agito la bacchetta e dico "Guida!"ad un'auto, bene, allora guida!
Funziona su altre cose? Non sono sicuro: quindi lo provo su un camion. Wow - guida anche tu! Poi lo provo su aerei, treni e 1 bosco (sono un tipo di mazza da golf che la gente usa per "guidare" una pallina da golf). Tutti guidano!
Ma funzionerebbe, diciamo, una tazza da tè? Errore: KAAAA-BOOOOOOM! non ha funzionato così bene. ====> Le tazze da tè non possono guidare !! duh !?
Questo è fondamentalmente il concetto di tipizzazione anatra. È un sistema da provare prima di acquistare . Se funziona, va tutto bene. Ma se fallisce, come una granata ancora in mano, ti esploderà in faccia.
In altre parole, siamo interessati a ciò che l'oggetto può fare , piuttosto che a ciò che l'oggetto è .
Esempio: lingue tipicamente statiche
Se eravamo preoccupati di cosa fosse effettivamente l'oggetto , allora il nostro trucco magico funzionerà solo su tipi preimpostati e autorizzati - in questo caso le auto, ma fallirà su altri oggetti che possono guidare : camion, ciclomotori, tuk-tuk ecc. Non funzionerà sui camion perché la nostra bacchetta magica si aspetta che funzioni solo sulle auto .
In altre parole, in questo scenario, la bacchetta magica aspetto molto da vicino a ciò che l'oggetto è (si tratta di una macchina?), Piuttosto che ciò che l'oggetto può fare (per esempio se le automobili, camion, ecc possono guidare).
L'unico modo in cui puoi guidare un camion è se riesci in qualche modo a far sì che la bacchetta magica si aspetti sia camion che automobili (forse "implementando un'interfaccia comune"). Se non sai cosa significhi, ignoralo per il momento.
Riepilogo: estrazione chiave
Ciò che è importante nella tipizzazione anatra è ciò che l'oggetto può effettivamente fare, piuttosto che ciò che l'oggetto è .
Considera che stai progettando una funzione semplice, che ottiene un oggetto di tipo Bird
e chiama il suo walk()
metodo. Esistono due approcci a cui puoi pensare:
Bird
, o il loro codice non verrà compilato. Se qualcuno vuole usare la mia funzione, deve essere consapevole che accetto solo Bird
sobjects
e chiamo semplicemente il walk()
metodo dell'oggetto . Quindi, se la object
lattina walk()
è corretta, se non è possibile la mia funzione fallirà. Quindi qui non è importante che l'oggetto sia Bird
o qualsiasi altra cosa, è importante che possa walk()
(questo è il tipo di anatra )Bisogna considerare che la tipizzazione duck può essere utile in alcuni casi, ad esempio Python usa molto la tipizzazione duck .
Wikipedia ha una spiegazione abbastanza dettagliata:
http://en.wikipedia.org/wiki/Duck_typing
la tipizzazione duck è uno stile di tipizzazione dinamica in cui l'insieme corrente di metodi e proprietà di un oggetto determina la semantica valida, piuttosto che la sua eredità da una particolare classe o implementazione di una specifica interfaccia.
La nota importante è probabile che con la tipizzazione anatra uno sviluppatore si preoccupi più delle parti dell'oggetto che vengono consumate piuttosto che del tipo reale sottostante.
Vedo molte risposte che ripetono il vecchio linguaggio:
Se sembra un'anatra e ciondola come un'anatra, è un'anatra
e poi immergiti in una spiegazione di cosa puoi fare con la digitazione dell'anatra, o in un esempio che sembra offuscare ulteriormente il concetto.
Non trovo molto aiuto.
Questo è il miglior tentativo di una semplice risposta inglese sulla digitazione di anatre che ho trovato:
Duck Typing significa che un oggetto è definito da ciò che può fare, non da ciò che è.
Ciò significa che siamo meno preoccupati della classe / tipo di un oggetto e più preoccupati di quali metodi possono essere chiamati su di esso e quali operazioni possono essere eseguite su di esso. Non ci interessa il suo tipo, ci preoccupiamo di cosa può fare .
Duck typing:
Se parla e cammina come un'anatra, allora è un'anatra
Questo è tipicamente chiamato rapimento ( ragionamento abduttivo o anche retroduzione , una definizione più chiara penso):
da C (conclusione, ciò che vediamo ) e R (regola, ciò che sappiamo ), accettiamo / decidiamo / assumiamo P (Premessa, proprietà ) in altre parole un dato fatto
... le basi stesse della diagnosi medica
con le anatre: C = cammina, parla , R = come un'anatra , P = è un'anatra
Torna alla programmazione:
l'oggetto o ha metodo / proprietà mp1 e interfaccia / tipo T richiede / definisce mp1
l'oggetto o ha metodo / proprietà mp2 e interfaccia / tipo T richiede / definisce mp2
...
Quindi, oltre ad accettare semplicemente mp1 ... su qualsiasi oggetto, purché soddisfi una definizione di mp1 ..., il compilatore / runtime dovrebbe anche andare bene con l'affermazione o è di tipo T
E bene, è il caso degli esempi sopra? La tipizzazione Duck è essenzialmente nessuna tipizzazione? O dovremmo chiamarlo tipizzazione implicita?
Guardare la lingua stessa può aiutare; mi aiuta spesso (non sono un madrelingua inglese).
In duck typing
:
1) la parola typing
non significa digitare su una tastiera (come era l'immagine persistente nella mia mente), significa determinare " che tipo di cosa è quella cosa? "
2) la parola duck
esprime come è fatta quella determinazione; è una specie di determinazione "libera", come in: " se cammina come un'anatra ... allora è un'anatra ". È "sciolto" perché la cosa può essere un'anatra o no, ma non importa se in realtà è un'anatra; ciò che conta è che posso farci ciò che posso fare con le anatre e aspettarmi comportamenti mostrati dalle anatre. Posso dargli da mangiare le briciole di pane e la cosa potrebbe andare verso di me o caricarmi o arretrare ... ma non mi divorerà come farebbe un grizzly.
So di non dare una risposta generalizzata. In Ruby non dichiariamo i tipi di variabili o metodi: tutto è solo una specie di oggetto. Quindi la regola è "Le classi non sono tipi"
In Ruby, la classe non è mai (OK, quasi mai) il tipo. Invece, il tipo di un oggetto è definito più da ciò che quell'oggetto può fare. In Ruby, chiamiamo questa anatra digitando. Se un oggetto cammina come un'anatra e parla come un'anatra, allora l'interprete è felice di trattarlo come se fosse un'anatra.
Ad esempio, potresti scrivere una routine per aggiungere informazioni sul brano a una stringa. Se provieni da uno sfondo C # o Java, potresti essere tentato di scrivere questo:
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)"
Abbraccia la tipografia di Ruby e scriverai qualcosa di molto più semplice:
def append_song(result, song)
result << song.title << " (" << song.artist << ")"
end
result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"
Non è necessario controllare il tipo di argomenti. Se supportano << (nel caso del risultato) o titolo e artista (nel caso del brano), tutto funzionerà. In caso contrario, il tuo metodo genererà comunque un'eccezione (proprio come avrebbe fatto se avessi controllato i tipi). Ma senza il controllo, il tuo metodo è improvvisamente molto più flessibile. Potresti passargli un array, una stringa, un file o qualsiasi altro oggetto che accoda usando <<, e funzionerebbe.
Duck Typing non è un suggerimento sul tipo!
Fondamentalmente per usare la "tipizzazione anatra" non sceglierai un tipo specifico ma piuttosto una gamma più ampia di sottotipi (non parliamo di eredità, quando intendo i sottotipi intendo "cose" che si adattano all'interno degli stessi profili) usando un'interfaccia comune .
Puoi immaginare un sistema che memorizza informazioni. Per scrivere / leggere le informazioni hai bisogno di una sorta di memoria e informazione.
I tipi di archiviazione possono essere: file, database, sessione ecc.
L'interfaccia ti farà conoscere le opzioni disponibili (metodi) indipendentemente dal tipo di archiviazione, il che significa che a questo punto nulla è implementato! In altre parole, l'interfaccia non sa nulla su come archiviare le informazioni.
Ogni sistema di archiviazione deve conoscere l'esistenza dell'interfaccia implementando i suoi stessi metodi.
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;
}
}
Quindi, ogni volta che devi scrivere / leggere informazioni:
$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 questo esempio si finisce per utilizzare Duck Typing nel costruttore di archiviazione:
function __construct(StorageInterface $storage) ...
Spero che abbia aiutato;)
Penso che sia confuso mescolare la digitazione dinamica, la digitazione statica e la digitazione anatra. La tipizzazione anatra è un concetto indipendente e persino un linguaggio tipizzato statico come Go, potrebbe avere un sistema di controllo del tipo che implementa la tipizzazione anatra. Se un sistema di tipi controllerà i metodi di un oggetto (dichiarato) ma non il tipo, potrebbe essere chiamato un linguaggio di tipizzazione duck.
Cerco di capire la famosa frase a modo mio: "La dose di Python non importa se un oggetto è una vera anatra o no. Tutto ciò che importa è se l'oggetto, prima" ciarlatano ", secondo" come un'anatra "."
C'è un buon sito web. http://www.voidspace.org.uk/python/articles/duck_typing.shtml#id14
L'autore ha sottolineato che la tipizzazione duck consente di creare le proprie classi con una propria struttura di dati interna, ma a cui si accede utilizzando la normale sintassi di Python.