Pergunta

Não há muita informação nas especificações sobre o tipo de atribuição, e certamente não há nada sobre o objetivo. Além de "fazer varargs de passagem funcionar", para que eu usaria a atribuição de tipo? Abaixo está alguns Scala Repl para a sintaxe e os efeitos do uso.

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
Foi útil?

Solução

A atribuição de tipo está apenas dizendo ao compilador que tipo você espera de uma expressão, de todos os tipos válidos possíveis.

Um tipo é válido se respeitar as restrições existentes, como variação e declarações de tipo, e é um dos tipos da expressão a que se aplica "é um", Ou há uma conversão que se aplica ao escopo.

Então, java.lang.String extends java.lang.Object, portanto, qualquer String também é um Object. No seu exemplo, você declarou que deseja a expressão s ser tratado como um Object, não a String. Como não há restrições impedindo isso e o tipo desejado é um dos tipos s é um, funciona.

Agora, por que você quer isso? Considere isto:

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)

Você também poderia ter corrigido isso por tipo de atrofação s no ss declaração, ou você poderia ter declarado ssé o tipo Set[AnyRef].

No entanto, as declarações de tipo alcançam a mesma coisa apenas desde que você esteja atribuindo um valor a um identificador. O que sempre pode fazer, é claro, se não se preocupa em espalhar o código com identificadores de um tiro. Por exemplo, o seguinte não compila:

def prefixesOf(s: String) = s.foldLeft(Nil) { 
  case (head :: tail, char) => (head + char) :: head :: tail
  case (lst, char) => char.toString :: lst
}

Mas isso faz:

def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) { 
  case (head :: tail, char) => (head + char) :: head :: tail
  case (lst, char) => char.toString :: lst
}

Seria bobagem usar um identificador aqui no lugar de Nil. E embora eu pudesse apenas escrever List[String]() Em vez disso, isso nem sempre é uma opção. Considere isso, por exemplo:

def firstVowel(s: String) = s.foldLeft(None: Option[Char]) { 
  case (None, char) => if ("aeiou" contains char.toLower) Some(char) else None
  case (vowel, _) => vowel
}

Para a referência, é isso que o Scala 2.7 Spec (15 de março de 2009) tem a dizer sobre a atribuição de tipo:

Expr1 ::= ...
        | PostfixExpr Ascription

Ascription ::= ‘:’ InfixType
             | ‘:’ Annotation {Annotation}
             | ‘:’ ‘_’ ‘*’

Outras dicas

Uma possibilidade é quando o material de nível de rede e protocolo serial, então isso:

val x = 2 : Byte

é muito mais limpo do que

val x = 2.asInstanceOf[Byte]

O segundo formulário também é uma conversão de tempo de execução (não tratada pelo compilador) e pode levar a algumas condições interessantes de excesso/fluxo.

Eu uso a atribuição de tipo em papel sobre orifícios na inferência do tipo de Scala. Por exemplo, dobrar uma coleção do tipo A pega um elemento inicial do tipo B e uma função (b, a) => b que é usado para dobrar os elementos da coleção no elemento inicial. O valor real do tipo B é inferido do tipo do elemento inicial. Como a lista de nil estende [nada], usá -la como um elemento inicial causa problemas:

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)

Como alternativa, você pode apenas usar list.empty [int] em vez de nil: list [int].

scala> x.foldLeft(List.empty[Int])( (acc,elem) => elem::acc )
res3: List[Int] = List(4, 3, 2, 1)

editar: list.empty [a] é implementado como

override def empty[A]: List[A] = Nil

(fonte)

Esta é efetivamente uma forma mais detalhada de nulo: lista [a

Você pode encontrar este tópico Iluminante, se um pouco complicado para seguir. O importante a ser observado é que você está adicionando dicas de restrição ao verificador de tipo - ele oferece um pouco mais de controle sobre o que essa fase de compilação está fazendo.

Tipo Inferência: podemos pular explicitamente o nome de algo em código -fonte, chamado de inferência de tipo. (Embora exigido em alguns casos excepcionais.)

Tipo Atribuído: Ser explícito sobre o tipo de algo é chamado de atribuição de tipo. Que diferença ele pode fazer?

ex: val x = 2: byte

Veja também: 1. Podemos dar explicitamente o tipo de retorno às nossas funções

def t1 : Option[Option[String]] = Some(None)

> t1: Option[Option[String]]

Outra maneira de declarar isso poderia ser:

def t2 = Some(None: Option[String])
> t2: Some[Option[String]]

Aqui não damos Option[Option[String]] Tipo de retorno explicitamente e o compilador inferiram como Some[Option[String]]. Por que Some[Option[String]] é porque usamos o tipo de atribuição na definição.

  1. Outra maneira de usar a mesma definição é:

    def t3 = Some(None)

    > t3: Some[None.type]

Desta vez, não contamos explicitamente nada ao compilador (nem esse defi). E inferiu nossa definição como algum [nenhum.type

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top