Domanda

Non c'è molto informazioni nelle specifiche su quale tipo attribuzione è, e certamente non è nulla in là per la finalità per esso. Altro che "fare passare il lavoro varargs", quello che vorrei utilizzare tipo attribuzione per? Di seguito alcune REPL scala per la sintassi e gli effetti del suo utilizzo.

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
È stato utile?

Soluzione

Tipo attribuzione è solo dire al compilatore che tipo che ci si aspetta da un'espressione, da tutti i possibili tipi validi.

Un tipo è valida se rispetta vincoli esistenti quali dichiarazioni varianza e tipo, ed è uno dei due tipi di espressione si applica a " è un ", o c'è una conversione si applica in ambito.

Quindi, java.lang.String extends java.lang.Object, pertanto ogni String è anche un Object. Nel tuo esempio hai dichiarato di voler la s espressione di essere trattato come un Object, non un String. Poiché non vi sono vincoli impediscono che e il tipo desiderato è uno dei tipi s è un , funziona.

Ora, perché si vuole che? Considerate questo:

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)

Si potrebbe anche avere corretto questo tipo ascripting s alla dichiarazione ss, o si potrebbe avere dichiarato il tipo di ss essere Set[AnyRef].

Tuttavia, dichiarazioni di tipo raggiungono la stessa cosa solo finché si sta assegnando un valore ad un identificatore. Quale può fare sempre, naturalmente, se non si preoccupano di sporcare il codice con identificatori one-shot. Ad esempio, il seguente non viene compilato:

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

Ma questo fa:

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

Sarebbe sciocco di utilizzare un identificatore qui al posto di Nil. E anche se ho potuto solo scrivere List[String]() invece, che non è sempre un'opzione. Considerate questo, per esempio:

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

Per il riferimento, questo è ciò che Scala 2.7 spec (15 marzo 2009 bozza) ha da dire sul tipo di attribuzione:

Expr1 ::= ...
        | PostfixExpr Ascription

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

Altri suggerimenti

Una possibilità è quando la rete e roba del livello di protocollo seriale, allora questo:

val x = 2 : Byte

è molto più pulita di quanto

val x = 2.asInstanceOf[Byte]

La seconda forma è anche una conversione runtime (non gestito dal compilatore) e potrebbe portare ad alcuni oltre / underflow condizioni interessanti.

Io uso tipo di attribuzione per mascherare buchi nel inferenza dei tipi di Scala. Ad esempio, foldLeft su un insieme di tipo A prende un elemento iniziale di tipo B e una funzione (B, A) => B che è utilizzata per ripiegare gli elementi della raccolta nell'elemento iniziale. Il valore effettivo di tipo B viene dedotto dal tipo dell'elemento iniziale. Dal momento che si estende Nil Lista [Niente], usandolo come elemento iniziale provoca problemi:

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)

In alternativa, si potrebbe utilizzare List.empty [Int] invece di Nil:. List [Int]

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

modifica: List.empty [A] viene implementato come

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

(fonte )

Questa è effettivamente una forma più dettagliata di Nil: Lista [A]

Si possono trovare questa discussione illuminante, se un po 'contorto da seguire. La cosa importante da notare è che si sta aggiungendo vincolo suggerimenti per il tipo di controllo -. Ti dà un po 'più di controllo su ciò che la fase di compilazione sta facendo

inferenza di tipo: Siamo in grado di saltare in modo esplicito dando Nome del tipo di qualcosa nel codice sorgente, chiamato inferenza di tipo

. (Anche se necessario in alcuni casi eccezionali.)

Tipo ascrizione: Essere espliciti circa il tipo di cosa è chiamato un tipo di ascrizione. Che differenza può fare?

es: val x = 2: Byte

vedi anche: 1. Possiamo esplicitamente dare tipo di ritorno per le nostre funzioni

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

> t1: Option[Option[String]]

Un altro modo di dichiarare questo potrebbe essere:

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

Qui non ha dato il tipo di ritorno esplicito Option[Option[String]] e Compiler dedotto come Some[Option[String]]. Perchè Some[Option[String]] è perché abbiamo usato il tipo attribuzione nella definizione.

  1. Un altro modo in cui possiamo usare la stessa definizione è:

    def t3 = Some(None)

    > t3: Some[None.type]

Questa volta non ha detto esplicitamente il nulla compilatore (né questo defi). E Ne ha dedotto la nostra definizione come alcuni [None.type]

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top