Il n'y a pas beaucoup d'informations dans la spécification sur le type d'attribution, et il n'y a certainement rien dans le but. À part "faire passer varargs", à quoi servirais-je? Vous trouverez ci-dessous un scala REPL pour la syntaxe et les effets de son utilisation.
scala> val s = "Dave"
s: Java.lang.String = Dave
scala> val p = s:Object
p: Java.lang.Object = Dave
scala> p.length
<console>:7: error: value length is not a member of Java.lang.Object
p.length
^
scala> p.getClass
res10: Java.lang.Class[_ <: Java.lang.Object] = class Java.lang.String
scala> s.getClass
res11: Java.lang.Class[_ <: Java.lang.Object] = class Java.lang.String
scala> p.asInstanceOf[String].length
res9: Int = 4
L'attribution de type indique simplement au compilateur quel type vous attendez d'une expression, parmi tous les types valides possibles.
Un type est valide s'il respecte les contraintes existantes, telles que les déclarations de variance et de type, et que ce soit l'un des types d'expression à laquelle il s'applique " est un ", ou bien une conversion qui s'applique dans la portée.
Donc, Java.lang.String extends Java.lang.Object
, donc toute String
est aussi une Object
. Dans votre exemple, vous avez déclaré que vous souhaitiez que l'expression s
soit traitée comme une Object
et non une String
. Puisqu'il n'y a pas de contrainte empêchant cela et que le type souhaité est l'un des types s
est un , cela fonctionne.
Maintenant, pourquoi voudriez-vous cela? Considère ceci:
scala> val s = "Dave"
s: Java.lang.String = Dave
scala> val p = s: Object
p: Java.lang.Object = Dave
scala> val ss = scala.collection.mutable.Set(s)
ss: scala.collection.mutable.Set[Java.lang.String] = Set(Dave)
scala> val ps = scala.collection.mutable.Set(p)
ps: scala.collection.mutable.Set[Java.lang.Object] = Set(Dave)
scala> ss += Nil
<console>:7: error: type mismatch;
found : scala.collection.immutable.Nil.type (with underlying type object Nil)
required: Java.lang.String
ss += Nil
^
scala> ps += Nil
res3: ps.type = Set(List(), Dave)
Vous pourriez aussi avoir corrigé cela en tapant le type ascripting s
dans la déclaration ss
ou vous auriez pu déclarer le type de ss
à Set[AnyRef]
.
Cependant, les déclarations de type obtiennent le même résultat uniquement si vous attribuez une valeur à un identificateur. Ce que l'on peut toujours faire, bien sûr, si on ne s'inquiète pas de mélanger le code avec des identifiants uniques. Par exemple, les éléments suivants ne sont pas compilés:
def prefixesOf(s: String) = s.foldLeft(Nil) {
case (head :: tail, char) => (head + char) :: head :: tail
case (lst, char) => char.toString :: lst
}
Mais cela fait:
def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) {
case (head :: tail, char) => (head + char) :: head :: tail
case (lst, char) => char.toString :: lst
}
Il serait idiot d'utiliser un identifiant ici à la place de Nil
. Et bien que je puisse simplement écrire List[String]()
à la place, ce n'est pas toujours une option. Considérez ceci, par exemple:
def firstVowel(s: String) = s.foldLeft(None: Option[Char]) {
case (None, char) => if ("aeiou" contains char.toLower) Some(char) else None
case (vowel, _) => vowel
}
Pour référence, voici ce que Scala 2.7 spec (version du 15 mars 2009) a à dire à propos de l'attribution de type:
Expr1 ::= ...
| PostfixExpr Ascription
Ascription ::= ‘:’ InfixType
| ‘:’ Annotation {Annotation}
| ‘:’ ‘_’ ‘*’
Une possibilité est lorsque les trucs de niveau réseau et protocole série, alors ceci:
val x = 2 : Byte
est beaucoup plus propre que
val x = 2.asInstanceOf[Byte]
La seconde forme est également une conversion à l'exécution (non gérée par le compilateur) et peut conduire à des conditions intéressantes de débordement/dépassement.
L'inférence de type: nous pouvons sauter explicitement le nom du type de quelque chose dans le code source, appelé Inférence de type (bien que requis dans des cas exceptionnels).
Attribution de type: Etre explicite sur le type de quelque chose s'appelle une assignation de type.
ex: val x = 2: octet
voir aussi: 1. Nous pouvons explicitement donner le type de retour à nos fonctions
def t1 : Option[Option[String]] = Some(None)
> t1: Option[Option[String]]
Une autre façon de déclarer cela pourrait être:
def t2 = Some(None: Option[String])
> t2: Some[Option[String]]
Ici, nous n'avons pas donné explicitement le type de retour Option[Option[String]]
et le compilateur l'a déduit en tant que Some[Option[String]]
. Pourquoi Some[Option[String]]
est-ce parce que nous avons utilisé l'attribution de type dans la définition.
Une autre façon d'utiliser la même définition est la suivante:
def t3 = Some(None)
> t3: Some[None.type]
Cette fois, nous n'avons rien dit explicitement au compilateur (ni cette définition). Et cela a déduit notre définition en tant que Some [None.type]
Vous pouvez trouver ce fil éclairant, si un peu compliqué à suivre. Il est important de noter que vous ajoutez des indicateurs de contrainte au vérificateur de type - cela vous donne un peu plus de contrôle sur le déroulement de la phase de compilation.
J'utilise l'attribution de type au papier sur les trous de l'inférence de type de Scala. Par exemple, foldLeft sur une collection de type A prend un élément initial de type B et une fonction (B, A) => B utilisée pour plier les éléments de la collection dans l'élément initial. La valeur réelle du type B est déduite du type de l'élément initial. Comme Nil étend la liste [Nothing], son utilisation en tant qu'élément initial pose des problèmes:
scala> val x = List(1,2,3,4)
x: List[Int] = List(1, 2, 3, 4)
scala> x.foldLeft(Nil)( (acc,elem) => elem::acc)
<console>:9: error: type mismatch;
found : List[Int]
required: scala.collection.immutable.Nil.type
x.foldLeft(Nil)( (acc,elem) => elem::acc)
^
scala> x.foldLeft(Nil:List[Int])( (acc,elem) => elem::acc )
res2: List[Int] = List(4, 3, 2, 1)
Alternativement, vous pouvez simplement utiliser List.empty [Int] au lieu de Nil: List [Int].
scala> x.foldLeft(List.empty[Int])( (acc,elem) => elem::acc )
res3: List[Int] = List(4, 3, 2, 1)
edit: List.empty [A] est implémenté en tant que
override def empty[A]: List[A] = Nil
C'est effectivement une forme plus verbeuse de Nil: List [A]