Pour les langues contemporaines, c'est juste du sucre syntaxique; d'une manière complètement indépendante de la langue, c'est plus que cela.
Auparavant, cette réponse indiquait simplement que c'était plus que du sucre syntaxique, mais si vous voyez dans les commentaires, Falco a soulevé le fait qu'il y avait une pièce du puzzle que les langues contemporaines semblaient toutes manquer; ils ne mélangent pas la surcharge de méthode avec la détermination dynamique de la fonction à appeler dans la même étape. Cela sera clarifié plus tard.
Voici pourquoi cela devrait être plus.
Prenons un langage qui prend en charge la surcharge de méthode et les variables non typées. Vous pouvez avoir les prototypes de méthodes suivants:
bool someFunction(int arg);
bool someFunction(string arg);
Dans certaines langues, vous seriez probablement résigné à savoir au moment de la compilation lequel de ceux-ci serait appelé par une ligne de code donnée. Mais dans certaines langues, toutes les variables ne sont pas typées (ou elles sont toutes implicitement typées comme Object
ou autre), alors imaginez construire un dictionnaire dont les clés correspondent à des valeurs de différents types:
dict roomNumber; // some hotels use numbers, some use letters, and some use
// alphanumerical strings. In some languages, built-in dictionary
// types automatically use untyped values for their keys to map to,
// so it makes more sense then to allow for both ints and strings in
// your code.
Maintenant, que se passe-t-il si vous souhaitez postuler someFunction
à l'un de ces numéros de chambre? Vous appelez cela:
someFunction(roomNumber[someSortOfKey]);
Est someFunction(int)
appelé, ou est someFunction(string)
appelé? Ici, vous voyez un exemple où ce ne sont pas des méthodes totalement orthogonales, en particulier dans les langues de niveau supérieur. Le langage doit déterminer - lors de l'exécution - lequel de ces éléments appeler, il doit donc toujours les considérer comme étant au moins un peu la même méthode.
Pourquoi ne pas simplement utiliser des modèles? Pourquoi ne pas simplement utiliser un argument non typé?
Flexibilité et contrôle plus fin. Parfois, utiliser des modèles / arguments non typés est une meilleure approche, mais parfois ils ne le sont pas.
Vous devez penser aux cas où, par exemple, vous pourriez avoir deux signatures de méthode qui prennent chacune un int
et un string
comme arguments, mais où l'ordre est différent dans chaque signature. Vous pouvez très bien avoir une bonne raison de le faire, car l'implémentation de chaque signature peut faire en grande partie la même chose, mais avec une torsion légèrement différente; la journalisation peut être différente, par exemple. Ou même s'ils font exactement la même chose, vous pouvez être en mesure de glaner automatiquement certaines informations uniquement dans l'ordre dans lequel les arguments ont été spécifiés. Techniquement, vous pouvez simplement utiliser des instructions pseudo-switch pour déterminer le type de chacun des arguments transmis, mais cela devient compliqué.
Alors, cet exemple suivant est-il une mauvaise pratique de programmation?
bool stringIsTrue(int arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
bool stringIsTrue(Object arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
bool stringIsTrue(string arg)
{
if (arg == "0")
{
return false;
}
else
{
return true;
}
}
Oui, en gros. Dans cet exemple particulier, cela pourrait empêcher quelqu'un d'essayer de l'appliquer à certains types primitifs et de récupérer un comportement inattendu (ce qui pourrait être une bonne chose); mais supposons simplement que j'ai abrégé le code ci-dessus, et que vous avez en fait des surcharges pour tous les types primitifs, ainsi que pour Object
s. Ensuite, ce bit de code suivant est vraiment plus approprié:
bool stringIsTrue(untyped arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
Mais que se passe-t-il si vous n'avez besoin de l'utiliser que pour int
s et string
s, et si vous voulez qu'il renvoie true en fonction de conditions plus simples ou plus compliquées en conséquence? Ensuite, vous avez une bonne raison d'utiliser la surcharge:
bool appearsToBeFirstFloor(int arg)
{
if (arg.digitAt(0) == 1)
{
return true;
}
else
{
return false;
}
}
bool appearsToBeFirstFloor(string arg)
{
string firstCharacter = arg.characterAt(0);
if (firstCharacter.isDigit())
{
return appearsToBeFirstFloor(int(firstCharacter));
}
else if (firstCharacter.toUpper() == "A")
{
return true;
}
else
{
return false;
}
}
Mais bon, pourquoi ne pas simplement donner à ces fonctions deux noms différents? Vous avez toujours la même quantité de contrôle à grain fin, n'est-ce pas?
Parce que, comme indiqué précédemment, certains hôtels utilisent des chiffres, certains utilisent des lettres et certains utilisent un mélange de chiffres et de lettres:
appearsToBeFirstFloor(roomNumber[someSortOfKey]);
// will treat ints and strings differently, without you having to write extra code
// every single spot where the function is being called
Ce n'est toujours pas exactement le même code exact que j'utiliserais dans la vraie vie, mais cela devrait illustrer le point que je fais très bien.
Mais ... Voici pourquoi ce n'est pas plus que du sucre syntaxique dans les langues contemporaines.
Falco a soulevé le point dans les commentaires que les langages actuels ne mélangent fondamentalement pas la surcharge de méthode et la sélection de fonction dynamique dans la même étape. La façon dont j'ai précédemment compris que certaines langues fonctionnaient était que vous pouviez surcharger appearsToBeFirstFloor
dans l'exemple ci-dessus, puis la langue déterminerait au moment de l'exécution la version de la fonction à appeler, en fonction de la valeur d'exécution de la variable non typée. Cette confusion provient en partie du travail avec des sortes de langages ECMA, comme ActionScript 3.0, dans lequel vous pouvez facilement randomiser quelle fonction est appelée sur une certaine ligne de code lors de l'exécution.
Comme vous le savez peut-être, ActionScript 3 ne prend pas en charge la surcharge de méthode. Quant à VB.NET, vous pouvez déclarer et définir des variables sans affecter explicitement un type, mais lorsque vous essayez de passer ces variables comme arguments à des méthodes surchargées, il ne veut toujours pas lire la valeur d'exécution pour déterminer la méthode à appeler; il veut plutôt trouver une méthode avec des arguments de type Object
ou aucun type ou quelque chose comme ça. Ainsi , le int
rapport string
exemple ci - dessus ne marcherait pas dans cette langue non plus . C ++ a des problèmes similaires, car lorsque vous utilisez quelque chose comme un pointeur void ou un autre mécanisme comme celui-ci, il vous oblige toujours à lever l'ambiguïté manuellement lors de la compilation.
Donc, comme le dit le premier en-tête ...
Pour les langues contemporaines, c'est juste du sucre syntaxique; d'une manière complètement indépendante de la langue, c'est plus que cela. Rendre la surcharge de méthode plus utile et plus pertinente, comme dans l'exemple ci-dessus, peut en fait être une bonne caractéristique à ajouter à un langage existant (comme cela a été largement implicitement demandé pour AS3), ou il pourrait également servir comme l'un des nombreux piliers fondamentaux pour la création d'un nouveau langage procédural / orienté objet.