78 votes

Pourquoi "éviter la surcharge des méthodes" ?

0 votes

Cela pourrait-il avoir un rapport avec le fait que Scala hérite de l'effacement des types de Java ?

1 votes

@Justin : Qu'est-ce que l'effacement des caractères a à voir avec ça ?

6 votes

Pourquoi ne demandez-vous pas à Jorge Ortiz pourquoi il déconseille la surcharge des méthodes ?

110voto

retronym Points 35066

La surcharge rend un peu plus difficile la transformation d'une méthode en fonction :

object A {
   def foo(a: Int) = 0
   def foo(b: Boolean) = 0
   def foo(a: Int, b: Int) = 0

   val function = foo _ // fails, must use = foo(_, _) or (a: Int) => foo(a)
}

Vous ne pouvez pas importer sélectivement une méthode parmi un ensemble de méthodes surchargées.

Il y a plus de chances qu'une ambiguïté surgisse lorsqu'on essaie d'appliquer des vues implicites pour adapter les arguments aux types de paramètres :

scala> implicit def S2B(s: String) = !s.isEmpty                             
S2B: (s: String)Boolean

scala> implicit def S2I(s: String) = s.length                               
S2I: (s: String)Int

scala> object test { def foo(a: Int) = 0; def foo(b: Boolean) = 1; foo("") }
<console>:15: error: ambiguous reference to overloaded definition,
both method foo in object test of type (b: Boolean)Int
and  method foo in object test of type (a: Int)Int
match argument types (java.lang.String)
       object test { def foo(a: Int) = 0; def foo(b: Boolean) = 1; foo("") }

Il peut tranquillement rendre les paramètres par défaut inutilisables :

object test { 
    def foo(a: Int) = 0; 
    def foo(a: Int, b: Int = 0) = 1 
}

Individuellement, ces raisons ne vous obligent pas à éviter complètement la surcharge. J'ai l'impression de passer à côté de problèmes plus importants.

UPDATE

Les preuves s'accumulent.

MISE À JOUR 2

  • Vous ne pouvez pas (actuellement) utiliser des méthodes surchargées dans les objets du paquet.
  • Les erreurs d'applicabilité sont plus difficile à diagnostiquer pour les appelants de votre API.

MISE À JOUR 3

  • La résolution statique des surcharges peut priver une API de toute sécurité de type :

    scala> object O { def apply[T](ts: T*) = (); def apply(f: (String => Int)) = () } defined object O

    scala> O((i: String) => f(i)) // oops, I meant to call the second overload but someone changed the return type of f when I wasn't looking...

2 votes

Actuellement, il y a aussi un bug dans scalac qui est déclenché par la surcharge dans certains cas. issues.scala-lang.org/browse/SI-7596 .

2 votes

Les deux premiers problèmes n'affectent pas toute utilisation valide de la surcharge. Classé un rapport de bogue pour le 3ème numéro. Le site la restriction des valeurs par défaut est un choix et pourrait en théorie être réparé. Défaut de la _.foo Le problème est l'inférence de type limitée de Scala, pas la surcharge. Vous répondez à la question, mais certaines des raisons sont dues à d'autres faiblesses de Scala qui pourraient être améliorées. La surcharge est plus efficace que le downcasting runtime une disjonction, ou un produit cartésien de noms est bruyant et se déconnecte d'une sémantique partagée.

0 votes

Les classes de types offrent une alternative à la surcharge dans certains cas. Le modèle magnétique ( spray.io/blog/2012-12-13-the-magnet-pattern ) pousse cette idée d'une manière intéressante.

11voto

Mushtaq Ahmed Points 2518

Gilad Bracha a publié un bon article expliquant cela il y a quelque temps :

http://gbracha.blogspot.com/2009/09/systemic-overload.html

8voto

Jorge Ortiz Points 3374

Les raisons que Gilad et Jason (retronym) donnent sont toutes de très bonnes raisons d'éviter la surcharge si possible. Les raisons de Gilad se concentrent sur les raisons pour lesquelles la surcharge est problématique en général, tandis que les raisons de Jason se concentrent sur les raisons pour lesquelles elle est problématique dans le contexte d'autres fonctionnalités de Scala.

À la liste de Jason, j'ajouterais que la surcharge interagit mal avec l'inférence de type. Pensez-y :

val x = ...
foo(x)

Un changement dans le type présumé de x pourrait modifier ce qui foo est appelée. Le site valeur de x ne doit pas changer, seul le type inféré de x ce qui peut se produire pour toutes sortes de raisons.

Pour toutes les raisons citées (et quelques autres que je suis sûr d'oublier), je pense que la surcharge des méthodes doit être utilisée avec le plus de parcimonie possible.

2 votes

Si vous ne voulez pas que cela se produise, vous déclarez le type de x. Si vous ne le déclarez pas, alors vous dites que vous souhaitez qu'il change. La sémantique de foo doit être la même pour chaque surcharge avec le même nombre de paramètres, sinon elle a été conçue de manière incorrecte. Quant à la limitation de la portée de la cascade bizarre de changements d'inférence, les méthodes publiques devraient toujours déclarer leurs types de retour. Je pense que c'est l'un des problèmes affectant la compatibilité binaire de Scala entre les versions.

1voto

ewernli Points 23180

Je pense que le conseil n'est pas destiné à scala en particulier, mais à l'OO en général (pour autant que je sache, scala est censé être un best-of-breed entre OO et fonctionnel).

Remplacement de c'est bien, c'est le cœur du polymorphisme et c'est central pour la conception OO.

Surcharge de travail d'autre part, est plus problématique. Avec la surcharge de méthodes, il est difficile de discerner quelle méthode sera réellement invoquée et c'est souvent une source de confusion. Il est également rare que l'on puisse justifier la nécessité de la surcharge. Le problème peut la plupart du temps être résolu d'une autre manière et je suis d'accord que la surcharge est une odeur.

Voici un article qui expliquent bien ce que je veux dire par "la surcharge est une source de confusion", ce qui, je pense, est la principale raison pour laquelle elle est déconseillée. C'est pour Java, mais je pense que cela s'applique aussi à Scala.

2 votes

Et Scala n'est pas principalement un langage OO de toute façon.

0 votes

@ewernli : C'est un lien utile. Modifie ta réponse pour y inclure ce lien et je t'upvote.

4 votes

@ewenli - Jorge est bien connu dans la communauté scala et le lien que Rahul a fourni était l'un des conseils scala de Jorge, mais votre réponse n'a rien à offrir sur les raisons pour lesquelles la surcharge est mauvaise. spécifiquement pour scala ce qui était clairement l'intention de la question. De plus, je n'ai aucune idée de la raison pour laquelle vous avez décidé que la question était confuse de quelque manière que ce soit - vous devriez simplement supprimer cela de votre réponse car c'est totalement injustifié. -1

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X