2010-10-13 5 views
7

Je voudrais écrire un alias de type pour raccourcir, sympa et encapsulé le code Scala. Supposons que j'ai une collection qui a la propriété d'être une liste de cartes, dont la valeur est des tuples. Mon type écrirait quelque chose comme List[Map[Int, (String, String)]], ou quelque chose de plus générique que mon application le permet. Je pourrais imaginer avoir un supertype demandant un Seq[MapLike[Int, Any]] ou tout ce qui flotte sur mon bateau, avec des sous-classes de béton plus spécifiques.Alias ​​de type Scala incluant l'objet compagnon [débutant]

Je voudrais alors écrire un alias pour ce type long.

class ConcreteClass { 
    type DataType = List[Map[Int, (String, String)]] 
    ... 
} 

Je puis partout utiliser heureusement ConcreteClass#DataType je peux prendre un, et l'utiliser.

Supposons maintenant ajouter une fonction

def foo(a : DataType) { ... } 

Et je veux l'appeler de l'extérieur avec une liste vide. Je peux appeler foo(List()), mais quand je veux changer mon type sous-jacent pour être un autre type de Seq, je vais devoir revenir et changer ce code aussi. D'ailleurs, ce n'est pas très explicite cette liste vide est prévue comme DataType. Et l'objet compagnon n'a pas les méthodes List associées, donc je ne peux pas appeler DataType() ou DataType.empty. Ca va être encore plus énervant quand j'ai besoin de listes non vides puisque je vais devoir écrire une partie significative de ce type long.

Est-ce que je peux demander à Scala de comprendre mon type comme étant la même chose, y compris l'objet compagnon avec ses méthodes créatrices, dans le but de raccourcir le code et de le blackboxer? Ou, une raison pour laquelle je ne devrais pas faire cela en premier lieu?

Répondre

7

La réponse est en fait assez simple:

class ConcreteClass { 
    type DataType = List[String] 
} 
object ConcreteClass { 
    val DataType = List 
} 
val d = ConcreteClass.DataType.empty 

Cela permet à mon code d'appeler ConcreteClass.DataType pour construire des listes avec toutes les méthodes de liste et peu d'effort.

Merci beaucoup à Oleg pour la perspicacité. Sa réponse est également préférable dans le cas où vous ne souhaitez pas déléguer à un appel List à ConcreteClass.DataType, mais contrôlez précisément ce que vous voulez autoriser les appelants à faire.

+2

Si vous n'avez pas l'intention de sous-classes de 'ConcreteClass' pour remplacer' DataType', vous feriez mieux de placer les alias 'type' et' val' dans l'objet compagnon (au lieu d'en avoir un dans la classe). C'est ainsi que fonctionnent les alias dans l'objet package scala. –

+0

Vous avez vraiment raison. Je vais le faire à partir de maintenant. Merci. – Jean

+1

Excepté d is type List [Nothing] – sourcedelica

5

Que pensez-vous de cela?

 
class ConcreteClass { 
    type DataType = List[String] 
} 
object DataType { 
    def apply(): ConcreteClass#DataType = Nil 
} 
//... 
val a = DataType() 

+0

Cela fonctionne. Merci. Cependant, avec cela, je dois définir chaque méthode de List pour faire ce que je veux, et c'est un peu verbeux. C'est très bien d'avoir le contrôle sur ce qu'on peut appeler aussi. Merci à votre réponse, je pense que j'ai obtenu la solution générique pour le "peut appeler toutes les méthodes de liste": le poster maintenant. Merci beaucoup :) – Jean