Je suis tombé sur le terme dactylographie en lisant des sujets aléatoires sur des logiciels en ligne et je ne les comprenais pas complètement.
Qu'est-ce que la «frappe de canard»?
C'est un terme utilisé dans les langages dynamiques qui n'ont pas de typage fort .
L'idée est que vous n'avez pas besoin d'un type pour invoquer une méthode existante sur un objet. Si une méthode est définie dessus, vous pouvez l'invoquer.
Le nom vient de la phrase "Si cela ressemble à un canard et que les charlatans sont comme un canard, c'est un canard".
Wikipedia a beaucoup plus d'informations.
La discussion sur la sémantique de la question est assez nuancée (et très théorique), mais voici l’idée générale:
Taper du canard
(“Si ça marche comme un canard et des charlatans comme un canard, alors c'est un canard.”) - oui mais qu'est-ce que ça veut dire? Ceci est mieux illustré par l'exemple:
Exemple: langages à typage dynamique
Imaginez que j'ai une baguette magique. Il a des pouvoirs spéciaux. Si j'agite la baguette et dit "Drive!" à une voiture, eh bien, ça roule!
Est-ce que ça marche sur d'autres choses? Pas sûr: j'essaye donc sur un camion. Wow - ça roule aussi! Je l’essaye ensuite dans les avions, les trains et 1 Woods (c’est un type de club de golf que les gens utilisent pour «conduire» une balle de golf). Ils conduisent tous!
Mais est-ce que ça marcherait, disons, une tasse de thé? Erreur: KAAAA-BOOOOOOM! cela n'a pas fonctionné si bien. ====> Les tasses de thé ne peuvent pas conduire !! duh !?
C'est fondamentalement le concept de la frappe de canard. C'est un système de type essayez avant d'acheter. Si cela fonctionne, tout va bien. Mais si ça échoue, eh bien, ça va exploser dans votre visage.
En d’autres termes, nous nous intéressons à ce que l’objet peut faire plutôt qu’à quel est l’objet.
Exemple: langages statiquement typés
Si nous étions concernés par ce que l'objet était réellement, alors notre tour de magie ne fonctionnera que sur des types autorisés pré-définis - dans ce cas des voitures, mais échouera sur d'autres objets pouvant conduire: camions, cyclomoteurs, tuk-tuks, etc. Cela ne fonctionnera pas sur les camions car notre baguette magique l'attend uniquement sur les voitures.
En d’autres termes, dans ce scénario, la baguette magique examine de très près ce que l’objet est (s’agit-il d’une voiture?) Plutôt que ce que l’objet peut faire (par exemple, si les voitures, les camions, etc. peuvent conduire).
La seule façon de conduire un camion est de pouvoir obtenir la baguette magique qui attend les deux camions et voitures (peut-être en "mettant en oeuvre une interface commune"). Si vous ne savez pas ce que cela signifie, alors ignorez-le pour le moment.
Résumé: clé de sortie
Ce qui est important dans le typage de canard, c’est ce que l’objet peut réellement faireplutôt que ce que l’objet est.
Considérez que vous concevez une fonction simple, qui obtient un objet de type Bird
et appelle sa méthode walk()
. Il existe deux approches auxquelles vous pouvez penser:
Bird
, sinon leur code ne sera pas compilé. Si quelqu'un veut utiliser ma fonction, il doit être conscient que je n'accepte que Bird
objects
et je viens d'appeler la méthode object walk()
. Donc, si la object
peut walk()
elle est correcte, sinon, ma fonction échouera. Donc ici il n’est pas important que l’objet soit une Bird
ou quoi que ce soit d’autre, il est important qu’il puisse walk()
(Ceci est duck typing)Il faut considérer que le duck typing peut être utile dans certains cas, par exemple, Python utilise beaucoup le duck typing.
Wikipedia a une explication assez détaillée:
http://en.wikipedia.org/wiki/Duck_typing
la frappe de canard est un style de dynamique taper dans lequel un objet est courant ensemble de méthodes et de propriétés détermine la sémantique valide, plutôt que son héritage d'un particulier classe ou implémentation d'un fichier interface.
Il est important de noter que probablement avec la saisie de code, le développeur est davantage concerné par les parties de l'objet consommées que par le type sous-jacent.
Je vois beaucoup de réponses qui répètent le vieil idiome:
Si cela ressemble à un canard et des charlatans à un canard, c'est un canard
puis plongez dans une explication de ce que vous pouvez faire avec la dactylographie, ou un exemple qui semble obscurcir davantage le concept.
Je ne trouve pas beaucoup d'aide.
C'est la meilleure tentative de réponse en anglais simple sur la frappe de canard que j'ai trouvée:
Duck Typing signifie qu'un objet est défini par ce qu'il peut faire, pas par Ce qu'il est.
Cela signifie que nous sommes moins préoccupés par la classe/le type d'un objet et plus par les méthodes pouvant être appelées et les opérations pouvant être exécutées. Nous ne nous soucions pas de son type, nous nous soucions de ce qu'il peut faire .
Duck Typing n'est pas un indice!
Fondamentalement, pour utiliser le "typage de canard", vous ne ciblerez pas un type spécifique mais plutôt un plus large éventail de sous-types (sans parler d'héritage, je veux dire des sous-types, je veux dire des "choses" qui correspondent aux mêmes profils) en utilisant une interface commune .
Vous pouvez imaginer un système qui stocke des informations. Pour écrire/lire des informations, vous avez besoin d’une sorte de stockage et d’informations.
Les types de stockage peuvent être: fichier, base de données, session, etc.
L'interface vous permettra de connaître les options disponibles (méthodes) quel que soit le type de stockage, ce qui signifie qu'à ce stade rien n'est implémenté! En d'autres termes, l'interface ne sait rien sur la manière de stocker des informations.
Chaque système de stockage doit connaître l'existence de l'interface en implémentant des méthodes identiques.
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;
}
}
Alors maintenant, chaque fois que vous avez besoin d'écrire/lire des informations:
$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');
Dans cet exemple, vous utilisez le constructeur Duck Typing in Storage:
function __construct(StorageInterface $storage) ...
J'espère que ça a aidé;)
Je sais que je ne donne pas de réponse généralisée. En Ruby, nous ne déclarons pas les types de variables ou de méthodes - tout n’est qu’une sorte d’objet . La règle est donc "Classes ne sont pas des types"
En Ruby, la classe n’est jamais (OK, presque jamais) le type. Au lieu de cela, le type d'un objet est davantage défini par ce que cet objet peut faire. En Ruby, nous appelons cette frappe de canard. Si un objet marche comme un canard et parle comme un canard, l'interprète est heureux de le traiter comme s'il s'agissait d'un canard.
Par exemple, vous écrivez peut-être une routine pour ajouter des informations sur une chanson à une chaîne. Si vous venez d'un contexte C # ou Java, vous pourriez être tenté d'écrire ceci:
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)"
Embrassez la frappe de Ruby avec le canard et vous écrirez quelque chose de beaucoup plus simple:
def append_song(result, song)
result << song.title << " (" << song.artist << ")"
end
result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"
Vous n'avez pas besoin de vérifier le type des arguments. S'ils appuient << (dans le cas du résultat) ou le titre et l'artiste (dans le cas de la chanson), tout fonctionnera. Si ce n’est pas le cas, votre méthode lèvera quand même une exception (comme cela aurait été le cas si vous aviez coché les types). Mais sans vérification, votre méthode est soudainement beaucoup plus flexible. Vous pouvez lui transmettre un tableau, une chaîne, un fichier ou tout autre objet ajouté avec <<, et cela fonctionnerait tout simplement.
Regarder la langue elle-même peut aider; cela m'aide souvent (je ne parle pas anglais).
Dans duck typing
:
1) Le mot typing
ne signifie pas taper sur un clavier (comme l’était l’image persistante dans mon esprit), cela veut dire déterminer " quel type de chose est cette chose? "
2) le mot duck
exprime comment cette détermination est effectuée; C'est un peu comme une détermination, comme dans: " si ça marche comme un canard ... alors c'est un canard ". C'est «lâche» parce que la chose peut être un canard ou non, mais peu importe qu'il s'agisse d'un canard ou non. ce qui compte, c’est de pouvoir faire avec ce que je peux faire avec les canards et d’attendre les comportements qu’ils présentent. Je peux lui donner à manger des miettes de pain et la chose peut aller vers moi, me charger ou m'éloigner ... mais elle ne me dévorera pas comme le ferait un grizzly.
Canard en train de taper:
S'il parle et marche comme un canard, alors c'est un canard
Ceci est typiquement appelé abduction (raisonnement abductif ou aussi appelé rétroduction, une définition plus claire je pense):
deC(conclusion, ce que nous voyons) etR(règle, ce que nous savons), nous acceptons/décidons/supposonsP(Premise, property) en d'autres termes, un fait donné
... la base même du diagnostic médical
avec des canards:C= se promène, parle,R= comme un canard,P= c'est un canard
Retour à la programmation:
l'objet o a une méthode/propriété mp1 et une interface/type T require/define mp1
l'objet o a la méthode/propriété mp2 et l'interface/type T requiert/définit mp2
...
Donc, plus que simplement accepter mp1 ... sur un objet aussi longtemps qu'il répond à une définition de mp1 ..., le compilateur/runtime devrait également convenir à l'assertion o est de type T
Et bien, est-ce le cas avec les exemples ci-dessus? Duck est-il en train de taper est essentiellement pas du tout? Ou devrions-nous appeler cela le typage implicite?
Traversée d'arbres avec technique de frappe de canards
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=" ")
Je pense qu'il est confus de mélanger dactylographie dynamique, dactylographie statique et dactylographie. Le typage de canard est un concept indépendant et même un langage typé statique comme Go, pourrait avoir un système de vérification de type qui implémente le typage de canard. Si un système de types vérifie les méthodes d'un objet (déclaré) mais pas le type, il peut être appelé langage de frappe.