La surcharge d'opérateurs en C ++ est considérée par beaucoup comme une mauvaise chose (tm), et une erreur à ne pas répéter dans les nouveaux langages. Il s'agissait certainement d'une fonctionnalité spécifiquement abandonnée lors de la conception de Java.
Maintenant que j'ai commencé à lire sur Scala, je trouve qu'il a ce qui ressemble beaucoup à une surcharge d'opérateurs (bien que techniquement, il ne soit pas surchargé car il n'a pas d'opérateurs, seulement des fonctions). Cependant, cela ne semble pas être qualitativement différent de la surcharge d'opérateurs en C ++, où, si je me souviens bien, les opérateurs sont définis comme des fonctions spéciales.
Ma question est donc de savoir ce qui fait de l'idée de définir "+" dans Scala une meilleure idée qu'elle ne l'était en C ++?
la source
Réponses:
C ++ hérite des véritables opérateurs bleus de C. J'entends par là que le "+" en 6 + 4 est très spécial. Vous ne pouvez pas, par exemple, obtenir un pointeur vers cette fonction +.
Scala, en revanche, n'a pas d'opérateurs de cette manière. Il a juste une grande flexibilité dans la définition des noms de méthode et un peu de priorité intégrée pour les symboles non-mot. Donc, techniquement, Scala n'a pas de surcharge d'opérateurs.
Quoi que vous vouliez l'appeler, la surcharge d'opérateurs n'est pas intrinsèquement mauvaise, même en C ++. Le problème est que les mauvais programmeurs en abusent. Mais franchement, je suis d'avis que priver les programmeurs de la capacité d'abuser de la surcharge des opérateurs ne met pas une goutte dans le seau de réparer toutes les choses dont les programmeurs peuvent abuser. La vraie réponse est le mentorat. http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html
Néanmoins, il existe des différences entre la surcharge d'opérateurs de C ++ et la dénomination de méthode flexible de Scala qui, à mon humble avis, rend Scala à la fois moins abusable et plus abusable.
En C ++, le seul moyen d'obtenir une notation in-fix est d'utiliser des opérateurs. Sinon, vous devez utiliser object.message (argument) ou pointer-> messsage (argument) ou function (argument1, argument2). Donc, si vous voulez un certain style DSL pour votre code, il y a une pression pour utiliser des opérateurs.
Dans Scala, vous pouvez obtenir une notation infixe avec n'importe quel message envoyé. "object message argument" est parfaitement correct, ce qui signifie que vous n'avez pas besoin d'utiliser des symboles non-mot juste pour obtenir la notation infixe.
La surcharge des opérateurs C ++ est essentiellement limitée aux opérateurs C. Combiné avec la limitation que seuls les opérateurs peuvent être utilisés infixe qui met la pression sur les gens pour essayer de mapper un large éventail de concepts non liés sur un nombre relativement limité de symboles comme "+" et ">>"
Scala autorise une vaste gamme de symboles valides sans mots comme noms de méthode. Par exemple, j'ai un DSL Prolog-ish intégré où vous pouvez écrire
Les symboles: -,!,? Et & sont définis comme des méthodes ordinaires. En C ++ seulement & serait valide donc une tentative de mapper ce DSL en C ++ nécessiterait des symboles qui évoquent déjà des concepts très différents.
Bien sûr, cela ouvre également Scala à un autre type d'abus. Dans Scala, vous pouvez nommer une méthode $! & ^% Si vous le souhaitez.
Pour d'autres langages qui, comme Scala, sont flexibles dans l'utilisation de fonctions et de noms de méthodes non-mot, voir Smalltalk où, comme Scala, chaque "opérateur" est juste une autre méthode et Haskell qui permet au programmeur de définir la priorité et la fixité des noms flexibles les fonctions.
la source
int main() {return (3).operator+(5);}
Résultats @Joshuaerror: request for member ‘operator+’ in ‘3’, which is of non-class type ‘int’
Seulement par l'ignorant. Il est absolument nécessaire dans un langage comme le C ++, et il est à noter que d'autres langages qui avaient commencé par adopter une vision «puriste» l'ont ajouté une fois que leurs concepteurs ont découvert à quel point c'était nécessaire.
la source
La surcharge des opérateurs n'a jamais été universellement considérée comme une mauvaise idée en C ++ - juste l'abus de la surcharge des opérateurs était considéré comme une mauvaise idée. On n'a pas vraiment besoin de surcharge d'opérateurs dans un langage car ils peuvent quand même être simulés avec des appels de fonctions plus verbeux. Éviter la surcharge des opérateurs en Java a rendu la mise en œuvre et la spécification de Java un peu plus simples et obligé les programmeurs à ne pas abuser des opérateurs. Il y a eu un débat dans la communauté Java sur l'introduction de la surcharge des opérateurs.
Les avantages et les inconvénients de la surcharge d'opérateurs dans Scala sont les mêmes qu'en C ++ - vous pouvez écrire du code plus naturel si vous utilisez la surcharge d'opérateurs de manière appropriée - et du code plus crypté et obscurci si vous ne le faites pas.
FYI: Les opérateurs ne sont pas définis comme des fonctions spéciales en C ++, ils se comportent comme n'importe quelle autre fonction - bien qu'il y ait quelques différences dans la recherche de nom, s'ils doivent être des fonctions membres et le fait qu'ils peuvent être appelés de deux manières: 1 ) syntaxe d'opérateur, et 2) syntaxe d'ID de fonction d'opérateur.
la source
add(2, multiply(5, 3))
?Cet article - « L'héritage positif de C ++ et Java » - répond directement à votre question.
Java a par erreur (selon l'auteur) omis la surcharge d'opérateurs parce que c'était compliqué en C ++, mais a oublié pourquoi (ou n'a pas réalisé que cela ne s'appliquait pas à Java).
Heureusement, les langages de niveau supérieur comme Scala offrent aux développeurs des options, tout en fonctionnant toujours sur la même JVM.
la source
Il n'y a rien de mal à surcharger l'opérateur. En fait, il y a quelque chose de mal à ne pas avoir de surcharge d'opérateurs pour les types numériques. (Jetez un œil à du code Java qui utilise BigInteger et BigDecimal.)
Cependant, C ++ a une tradition d'abuser de cette fonctionnalité. Un exemple souvent cité est que les opérateurs de décalage de bits sont surchargés pour effectuer des E / S.
la source
=
place<<
et>>
aux premiers jours de C ++, mais a rencontré des problèmes car il n'avait pas la bonne priorité d'opérateur (c'est-à-dire qu'il recherche arguments à gauche ou à droite en premier). Donc, ses mains étaient un peu liées sur ce qu'il pouvait utiliser.En général, ce n'est pas une mauvaise chose.
Les nouveaux langages tels que C # ont également une surcharge d'opérateurs.
C'est l'abus de surcharge de l'opérateur qui est une mauvaise chose.
Mais il y a aussi des problèmes de surcharge d'opérateurs tels que définis dans C ++. Parce que les opérateurs surchargés ne sont que du sucre syntaxique pour les appels de méthode, ils se comportent comme une méthode. D'un autre côté, les opérateurs intégrés normaux ne se comportent pas comme des méthodes. Ces incohérences peuvent poser des problèmes.
Sur le dessus de mes opérateurs de tête
||
et&&
.Les versions intégrées de ceux-ci sont des opérateurs de raccourcis. Cela n'est pas vrai pour les versions surchargées et a causé quelques problèmes.
Le fait que + - * / retournent tous le même type sur lequel ils opèrent (après la promotion de l'opérateur)
Les versions surchargées peuvent renvoyer n'importe quoi (c'est là que l'abus s'installe, si vos opérateurs commencent à renvoyer un type d'arbitre auquel l'utilisateur ne s'attendait pas) les choses descendent).
la source
La surcharge des opérateurs n'est pas quelque chose dont vous "avez vraiment besoin" très souvent, mais lorsque vous utilisez Java, si vous atteignez un point où vous en avez vraiment besoin, cela vous donnera envie de vous arracher les ongles juste pour que vous ayez une excuse pour arrêter de taper .
Ce code que vous venez de trouver déborde longtemps? Oui, vous allez devoir retaper le tout pour que cela fonctionne avec BigInteger. Il n'y a rien de plus frustrant que de devoir réinventer la roue juste pour changer le type d'une variable.
la source
Guy Steele a fait valoir que la surcharge des opérateurs devrait également être en Java, dans son discours d'ouverture "Cultiver un langage" - il y a une vidéo et une transcription de celui-ci, et c'est vraiment un discours incroyable. Vous vous demanderez de quoi il parle pour les deux premières pages, mais si vous continuez à lire, vous verrez le point et atteindrez l'illumination. Et le fait même qu'il puisse faire un tel discours est également incroyable.
Dans le même temps, cette conférence a inspiré de nombreuses recherches fondamentales, y compris probablement Scala - c'est l'un de ces articles que tout le monde devrait lire pour travailler sur le terrain.
Pour revenir au point, ses exemples concernent principalement des classes numériques (comme BigInteger, et des trucs plus étranges), mais ce n'est pas essentiel.
Il est vrai, cependant, qu'une mauvaise utilisation de la surcharge d'opérateurs peut conduire à des résultats terribles, et que même des utilisations appropriées peuvent compliquer les choses, si vous essayez de lire du code sans étudier un peu les bibliothèques qu'il utilise. Mais est-ce une bonne idée? OTOH, ces bibliothèques ne devraient-elles pas essayer d'inclure une feuille de triche pour leurs opérateurs?
la source
Je crois que CHAQUE réponse a manqué cela. En C ++, vous pouvez surcharger les opérateurs autant que vous le souhaitez, mais vous ne pouvez pas affecter la priorité avec laquelle ils sont évalués. Scala n'a pas ce problème, IIRC.
Quant à ce que ce soit une mauvaise idée, outre les problèmes de priorité, les gens ont des significations vraiment stupides pour les opérateurs, et cela facilite rarement la lisibilité. Les bibliothèques Scala sont particulièrement mauvaises pour cela, des symboles loufoques que vous devez mémoriser à chaque fois, les responsables de la bibliothèque collant la tête dans le sable en disant: «vous n'avez besoin de l'apprendre qu'une seule fois». Génial, maintenant j'ai besoin d'apprendre la syntaxe cryptique d'un auteur «intelligent» * le nombre de bibliothèques que je souhaite utiliser. Ce ne serait pas si grave s'il existait une convention de TOUJOURS fournir une version alphabétisée des opérateurs.
la source
La surcharge d'opérateurs n'était pas une invention C ++ - elle venait d'Algol IIRC et même Gosling ne prétend pas que c'est une mauvaise idée en général.
la source
La seule chose mal connue en C ++ est le manque de capacité à surcharger [] = en tant qu'opérateur séparé. Cela pourrait être difficile à implémenter dans un compilateur C ++ pour ce qui n'est probablement pas une raison évidente mais qui en vaut largement la peine.
la source
Comme les autres réponses l'ont souligné; la surcharge de l'opérateur lui-même n'est pas nécessairement mauvaise. Ce qui est mauvais quand il est utilisé de manière à rendre le code résultant peu évident. Généralement, lorsque vous les utilisez, vous devez leur faire faire la chose la moins surprenante (avoir opérateur + do division causerait des problèmes pour l'utilisation d'une classe rationnelle) ou comme le dit Scott Meyers:
Maintenant, certaines personnes ont poussé la surcharge d'opérateurs à l'extrême avec des choses comme boost :: spirit . À ce niveau, vous n'avez aucune idée de la façon dont il est implémenté mais cela crée une syntaxe intéressante pour obtenir ce que vous voulez. Je ne sais pas si c'est bon ou mauvais. Cela semble bien, mais je ne l'ai pas utilisé.
la source
Je n'ai jamais vu un article affirmant que la surcharge des opérateurs C ++ est mauvaise.
Les opérateurs définissables par l'utilisateur permettent un plus haut niveau d'expressivité et de convivialité pour les utilisateurs de la langue.
la source
AFAIK, Il n'y a rien de spécial dans les fonctions d'opérateur par rapport aux fonctions membres "normales". Bien sûr, vous n'avez qu'un certain ensemble d'opérateurs que vous pouvez surcharger, mais cela ne les rend pas très spéciaux.
la source