Scala: Résumé des types de vs génériques
Je lisais Une Visite de la Scala: Résumé des Types de. Quand est-il préférable d'utiliser des types abstraits?
Par exemple,
abstract class Buffer {
type T
val element: T
}
plutôt que génériques, par exemple,
abstract class Buffer[T] {
val element: T
}
Vous devez vous connecter pour publier un commentaire.
Vous avez un bon point de vue sur cette question ici:
Le But de la Scala de Type du Système
Une Conversation avec Martin Odersky, Partie III
par Bill Venners et Frank Sommers (18 Mai 2009)
Mise à jour (October2009): ce qui suit ci-dessous a été effectivement illustré dans ce nouvel article par Bill Venners:
Type abstrait Membres rapport à des Paramètres de Type Générique en Scala (voir le résumé à la fin)
(Voici l'extrait pertinent de la première entrevue, Mai 2009, c'est moi qui souligne)
Principe général
Il y a toujours eu deux notions d'abstraction:
En Java, vous avez également la fois, mais cela dépend de ce que vous abstraire de plus.
En Java, vous avez des méthodes abstraites, mais vous ne pouvez pas passer d'une méthode en tant que paramètre.
Vous n'avez pas le résumé, mais vous pouvez passer une valeur d'un paramètre.
Et, de même, vous n'avez pas de type abstrait membres, mais vous pouvez spécifier un type de paramètre.
Donc en Java, vous avez également tous les trois de ceux-ci, mais il y a une distinction à propos de ce principe d'abstraction que vous pouvez utiliser pour ce genre de choses. Et on pourrait dire que cette distinction est assez arbitraire.
La Scala Façon
Nous avons décidé de la mêmes principes de construction pour tous les trois sortes de membres.
Vous pouvez donc avoir le résumé ainsi que la valeur des paramètres.
Vous pouvez passer des méthodes (ou fonctions) en tant que paramètres, ou vous pouvez abstraite au-dessus d'eux.
Vous pouvez spécifier les types de paramètres, ou vous pouvez abstraite au-dessus d'eux.
Et ce que nous obtenons sur le plan conceptuel, c'est que nous pouvons modéliser l'un pour l'autre. Au moins en principe, on peut exprimer toutes sortes de paramétrage comme une forme d'abstraction orientée objet. Donc dans un sens on pourrait dire Scala est un plus orthogonale et complet de la langue.
Pourquoi?
Ce, en particulier, résumé des types de acheter de vous, c'est un joli traitement pour ces covariance des problèmes nous avons parlé auparavant.
Un problème standard, qui a été autour pendant un long moment, c'est le problème des animaux et des aliments.
Le puzzle était pour avoir une classe
Animal
avec une méthode,eat
, qui mange de la nourriture.Le problème est que si nous sous-classe des Animaux et ont une classe de Vache, alors ils ne mangent que de l'Herbe et non arbitraire de la nourriture. Une Vache ne pouvais pas manger un Poisson, par exemple.
Ce que vous voulez est d'être en mesure de dire que la Vache a un manger méthode qui ne mange que de l'Herbe et pas autres choses.
En fait, vous ne pouvez pas le faire en Java, car il s'avère, vous pouvez construire des situations malsaines, comme le problème de l'attribution d'un Fruit à un Apple variable dont j'ai parlé plus tôt.
La réponse est que vous ajoutez un type abstrait dans l'Animal de la classe.
Vous dire, mon nouvel Animal de la classe a un type de
SuitableFood
, qui je ne sais pas.C'est donc un type abstrait. Vous ne donnez pas une mise en œuvre de ce type. Ensuite, vous avez une
eat
méthode qui ne mange que deSuitableFood
.Et puis, dans la
Cow
classe, je dirais, OK, j'ai une Vache, qui s'étend de la classeAnimal
, et pourCow type SuitableFood equals Grass
.Donc résumé des types de fournir cette notion de type dans une super-classe que je ne connais pas, que j'ai ensuite remplir plus tard dans les sous-classes de quelque chose, je ne sais.
Même avec un paramétrage?
En effet vous pouvez. Vous pouvez paramétrer la classe Animal avec le genre de nourriture qu'il mange.
Mais dans la pratique, lorsque vous le faites avec beaucoup de choses différentes, elle conduit à une explosion de paramètres, et généralement, ce qui est plus, dans limites des paramètres.
En 1998 ECOOP, Kim Bruce, Phil Wadler, et j'ai eu un papier où nous avons montré que comme vous augmentez le nombre de choses que vous ne savez pas, le programme typique va croître quadratiquement.
Il y a donc de très bonnes raisons de ne pas faire de paramètres, mais ces membres abstraits, parce qu'ils ne vous donnent pas cette quadratique exploser.
thatismatt demande dans les commentaires:
Je ne suis pas sûr que la relation qui existe entre l'utilisation de résumé ou de types génériques.
Ce qui est différent est:
De comprendre ce que Martin est de parler de quand il s'agit de "l'explosion de paramètres, et généralement, ce qui est plus, dans limites des paramètres", et son quadratiquement de la croissance lorsque le type abstrait sont modélisés à l'aide de médicaments génériques, vous pouvez envisager le papier "Évolutive Composant Abstraction" écrit par... Martin Odersky, et Matthias Zenger pour OOPSLA 2005, référencé dans le publications du projet Palcom (terminé en 2007).
Des extraits pertinents
Définition
(Note: la Famille polymorphisme a été proposé pour les langages orientés objet comme une solution à l'appui réutilisables encore de type sécurisé mutuellement récursives classes.
Une idée clé de la famille polymorphisme est la notion de famille, qui sont utilisés pour groupe mutuellement récursives classes)
délimitée type d'abstraction
(Remarque, de la part de Pierre de mise en conserve, William Cook, Walter Hill, Walter Olthoff papier:
Délimitée quantification a été introduit par Cardelli et Wegner comme un moyen de taper des fonctions qui opèrent de manière uniforme sur tous les sous-types d'un type donné.
Ils ont défini un simple "objet" modèle et utilisé délimitée quantification par type de fonctions de contrôle qui ont du sens sur tous les objets ayant un ensemble spécifié de "attributs".
Une présentation plus réaliste des langages orientés objet permettrait à des objets qui sont des éléments de de manière récursive les types définis par l'.
Dans ce contexte, dans les limites de quantification ne sert plus à sa destination. Il est facile de trouver les fonctions qui a du sens sur tous les objets ayant un ensemble de méthodes, mais qui ne peuvent pas être saisis dans le Cardelli-Wegner système.
Pour fournir une base pour tapé fonctions polymorphes dans les langages orientés objet, nous introduisons F-bornée quantification)
Deux faces d'une même pièces
Il existe deux principales formes de l'abstraction dans les langages de programmation:
La première forme est typique pour les langages fonctionnels, tandis que la deuxième forme est généralement utilisée dans les langages orientés objet.
Traditionnellement, Java prend en charge le paramétrage de valeurs, et membre de l'abstraction pour les opérations.
La plus récente de Java 5.0 avec les génériques prend en charge le paramétrage également pour les types.
Les arguments, y compris pour les médicaments génériques en Scala sont de deux ordres:
Tout d'abord, l'encodage dans l'abstrait n'est pas si simple à faire à la main. En plus de la perte de la concision, il y a aussi le problème des accidents de nom
les conflits entre l'abstrait type de noms qui émulent des paramètres de type.
Deuxième, génériques et abstraits types habitude de servir des rôles distincts dans la Scala de programmes.
type de client code.
Ce dernier se pose en particulier dans deux cas:
Dans un système délimité polymorphisme, la réécriture de type abstrait dans les génériques pourrait entraîner une quadratique extension de type de limites.
Mise À Jour Octobre 2009
Type abstrait Membres rapport à des Paramètres de Type Générique en Scala (Bill Venners)
(l'emphase est mienne)
Exemple:
trait C[T <: Ordered[T]]
. Et dépendant de la méthode de types de mentionné pour la famille polymorphisme peut également être fait avec les paramètres de type. N'apparaît qu'à la quadratique explosion de type point de limites reste. Voir aussi.abstract class A { def a[T](t: T): T }
Comment puis-je résumé sur la méthodea
avec le paramétrage?J'ai eu la même question quand je lisais à propos de la Scala.
L'avantage de l'utilisation de génériques, c'est que vous êtes la création d'une famille de types. Personne n'aura besoin à la sous-classe
Buffer
—il peut simplement utiliserBuffer[Any]
,Buffer[String]
, etc.Si vous utilisez un type abstrait, alors les gens vont être obligés de créer une sous-classe. Les gens auront besoin les classes comme
AnyBuffer
,StringBuffer
, etc.Vous devez décider ce qui est mieux pour votre besoin particulier.
Buffer { type T <: String }
ouBuffer { type T = String }
en fonction de vos besoinsVous pouvez utiliser les types abstract en conjonction avec les paramètres de type d'établir des modèles personnalisés.
Imaginons que vous avez besoin d'établir un modèle connecté avec trois traits:
dans la façon dont les arguments mentionnés dans les paramètres de type AA,BB,CC lui-même respectueusement
Vous pouvez venir avec un certain type de code:
qui ne fonctionne pas de cette manière simple, en raison de paramètre de type d'obligations. Vous devez il covariante d'hériter correctement
Présente un échantillon de la compilation, mais elle fixe des exigences fortes sur la variance des règles et ne peut pas être utilisé dans certaines occasions
Le compilateur objet avec des tas de variance vérifier les erreurs
Dans ce cas, vous peut recueillir toutes les exigences de type supplémentaire de traits de caractère et de paramétrer d'autres traits plus il
Maintenant, nous pouvons écrire en béton pour la représentation des modèles décrits, définir la gauche et rejoindre les méthodes de toutes les classes et obtenir le droit et le double pour gratuit
Donc, à la fois abstrait types de paramètres de type et sont utilisés pour créer des abstractions. Ils ont tous deux faibles et points forts. Résumé types sont plus spécifiques et capables de décrire tout type de structure, mais il est verbeux et nécessitent explicite spécifiée. Les paramètres de Type peut créer des tas de types instantanément, mais vous donne plus de s'inquiéter à propos de l'héritage et le type de limites.
Ils donnent synergie les uns des autres et peuvent être utilisés conjointement pour créer des complexes des abstractions qui ne peut pas être exprimée par un seul d'entre eux.