Dans quelles situations les types abstraits devraient-ils être préférés aux paramètres de type?Types abstraits et paramètres de type
Répondre
Pour ajouter à mon previous answer on Abstract type vs. parameters, vous avez aussi les JESSE EICHAR's recent blog post (2010, 3 mai) mettant en évidence quelques différences importantes:
trait C1[A] {
def get : A
def doit(a:A):A
}
trait C2 {
type A
def get : A
def doit(a:A):A
}
En C2
cas, le paramètre est « enterré » (comme un résumé interne type).
(sauf, comme retronym le dit, il est pas réellement enterré, voir ci-dessous)
Alors qu'avec type générique, le paramètre est explicitement mentionné, aider d'autres expressions de savoir quel type ils sont censés utiliser
So (C1: paramètre):
//compiles
def p(c:C1[Int]) = c.doit(c.get)
Il compile, mais vous exposer explicitement le type 'A
' que vous souhaitez utiliser.
et (C2: type abstrait):
// doesn't compile
def p2(c:C2) = c.doit(c.get)
<console>:6: error: illegal dependent method type
def p2(c:C2) = c.doit(c.get)
^
Il ne compile pas parce que 'A
' est jamais mentionné dans la définition de p2, donc doit
ne sait pas au type de compilation ce qu'il est censé revenir .
Lorsque vous utilisez le type abstrait et vouloir éviter tout type « fuite » à l'interface (par exemple vouloir exposer ce qui A
'est en fait), vous pouvez spécifier un type très générique comme un retour pour p2 :
// compiles because the internals of C2 does not leak out
def p(c:C2):Unit = c.doit(c.get)
Ou vous pouvez "fixer" ce type directement dans la fonction doit
:
def doit(a:A):Int
au lieu de def doit(a:A):A
, ce qui signifie:
def p2(c:C2) = c.doit(c.get)
compilera (même si p2 ne mentionne pas tout type de retour)
Enfin (commentaire de retronym) vous pouvez spécifier A
soit explicitement par le raffinage C2 paramètre abstrait:
scala> def p2(c:C2 { type A = Int }): Int = c.doit(c.get)
p2: (c: C2{type A = Int})Int
Ou par ajouter un paramètre type (et affiner le type abstrait C2 avec!)
scala> def p2[X](c:C2 { type A = X }): X = c.doit(c.get)
p2: [X](c: C2{type A = X})X
donc abstraite sont recommandées:
- Lorsque vous souhaitez masquer une définition exacte d'un membre de type de code client, utilisez type abstrait comme dans
C2
(mais se méfier de la définition de la fonction en utilisantC2
) - Lorsque vous souhaitez remplacer le type covariant dans les sous-classes de
C2
, utilisez type abstrait (avec l'abstraction de type borné) - Lorsque vous voulez mélanger dans les définitions de ces
C2
types par des traits, utilisez type abstrait (vous n'aurez pas «A
» pour traiter lors du mélangeC2
avec votre classe: vous mélangez seulementC2
)
Pour le reste, où type simple instanciation est nécessaire, les paramètres d'utilisation.
(si vous savez que aucune prolongation ne sera nécessaire, mais vous devez toujours gérer plusieurs types: c'est-ce que les types de paramètres sont pour)
retronym ajoute:
Les principales différences sont
- variance:
C2
ne peut être invariant dansA
, - la façon dont les éléments de type peut être sélectivement écrasées dans un sous-type (alors que les paramètres de type doivent être redéclaré et transmis au supertype)
(comme illustrating here:
trait T1 {
type t
val v: t
}
trait T2 extends T1 {
type t <: SomeType1
}
trait T3 extends T2 {
type t <: SomeType2 // where SomeType2 <: SomeType1
}
class C extends T3 {
type t = Concrete // where Concrete <: SomeType2
val v = new Concrete(...)
}
)
Ce n'est pas vraiment enterré: 'def p2 (c: C2 {type A = Int}): Int = c.doit (c.get)'. Ou: 'def p2 [X] (c: C2 {type A = X}): X = c.doit (c.get)'. Les principales différences sont la variance ('C2' ne peut être invariant que dans' A'), et la manière dont les membres de type peuvent être sélectivement remplacés dans un sous-type alors que les paramètres de type doivent être redéclarés et transmis au supertype. – retronym
@retronym: * "Les principales différences sont la variance ... et la manière dont les membres de type peuvent être sélectivement écrasés" * Cela signifie-t-il que tout ce qu'il est possible de faire avec l'un d'eux est possible avec l'autre? Sauf pour les deux aspects que vous mentionnez. La seule autre différence est la syntaxe? – Lii
- 1. Génériques Type paramètres et types
- 2. Problèmes avec les types abstraits et les interafaces comme paramètres de type génériques avec la contrainte new()
- 3. Renvoyer des types abstraits via REST
- 4. Comment utiliser Scala cette typage, types abstraits, etc pour implémenter un type de soi?
- 5. Types abstraits dans la définition de service Web (wsdl)
- 6. Résumé Paramètres Types/types Scala
- 7. plusieurs types de paramètres dans les classes de type haskell
- 8. JavaScript types de paramètres constructeur
- 9. Comment définir de manière centralisée IComparable sur les types abstraits (interface) dans F #
- 10. Utilisation de génériques avec des types de données abstraits en Java
- 11. C++ - Utilisation de std :: count() avec des types de données abstraits?
- 12. Paramètres .NET Types de fichiers disponibles
- 13. Fonctions avec types de paramètres génériques
- 14. fichier de paramètres .Net, types complexes et sérialisation
- 15. plusieurs paramètres de type
- 16. Obtenir les paramètres Type et no. de paramètres pour une fonction dans Visual Studio Editor (C#)
- 17. Utilisation de paramètres avec des types complexes
- 18. Fourniture de noms de paramètres pour les types de délégués
- 19. Quels sont les exemples concrets de mots clés abstraits nouveaux/virtuels/overrides/abstraits?
- 20. Gérer élégamment différents types de paramètres
- 21. Paramètres de type non-système optionnels
- 22. Enregistrement des paramètres des types personnalisés
- 23. C#: Restriction de types de paramètres de la méthode (pas les paramètres génériques)
- 24. Comment puis-je définir plusieurs types avec le même nom et différents paramètres de type à l'aide de Reflection Emit?
- 25. Format standard pour arbres syntaxiques concrets et abstraits
- 26. Comment identifier les membres abstraits par réflexion
- 27. Attraper types d'exception donnés en tant que paramètres de type en C# 2.0
- 28. Type de table mixte avec d'autres types comme paramètres à Stored Procedured C#
- 29. Types de données C# et types de données MySql
- 30. Utilisation de 'Type' et 'Enum' comme paramètres dans .NET
N'est-il pas déjà discuté dans http://stackoverflow.com/questions/1154571/scala-abstract-types-vs-generics/1154727#1154727? – VonC
@VonC: J'ai vu cette réponse mais je ne l'ai pas trouvée satisfaisante. –
J'essaie de l'illustrer ci-dessous, avec un blog récent de Jesse EICHAR. – VonC