Was ist der Zweck von Typ -Erschreibungen in Scala?
-
21-09-2019 - |
Frage
Es gibt nicht viele Informationen in der Spezifikation darüber, welcher Typ -Zuschreibung ist, und es gibt sicherlich nichts an dem Zweck dafür. Wofür würde ich abgesehen von "Durchgangsvarargs funktionieren", wofür ich einen Typ -Abruf verwenden würde? Unten finden Sie einige Scala -Replungen für die Syntax und die Auswirkungen der Verwendung.
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ösung
Typ -Zuschreibung sagt dem Compiler nur, welchen Typ Sie von einem Ausdruck erwarten, von allen möglichen gültigen Typen.
Ein Typ ist gültig, wenn er vorhandene Einschränkungen respektiert, wie z. B. Varianz- und Typdeklarationen, und es ist entweder einer der Typen, auf den er gilt. "ist ein", oder es gibt eine Konvertierung, die im Umfang gilt.
So, java.lang.String extends java.lang.Object
, deshalb alle String
ist auch ein Object
. In Ihrem Beispiel haben Sie erklärt, dass Sie den Ausdruck wollen s
als ein behandelt werden Object
, kein String
. Da es keine Einschränkungen gibt, die dies verhindern und der gewünschte Typ einer der Typen ist s
ist ein, Es klappt.
Warum willst du das? Bedenken Sie:
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)
Sie hätten dies auch durch Typ -Aufschrift behoben haben können s
bei ss
Erklärung oder Sie hätten deklarieren können ss
Typtyp zu sein Set[AnyRef]
.
Typ -Deklarationen erreichen jedoch nur so lange, wie Sie einem Kennung einen Wert zuweisen. Welches kann natürlich immer, wenn man den Code mit One-Shot-Kennungen nicht darum kümmert. Zum Beispiel wird das Folgende nicht kompiliert:
def prefixesOf(s: String) = s.foldLeft(Nil) {
case (head :: tail, char) => (head + char) :: head :: tail
case (lst, char) => char.toString :: lst
}
Aber das tut:
def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) {
case (head :: tail, char) => (head + char) :: head :: tail
case (lst, char) => char.toString :: lst
}
Es wäre albern, hier anstelle von einen Kennung zu verwenden Nil
. Und obwohl ich einfach schreiben konnte List[String]()
Stattdessen ist das nicht immer eine Option. Betrachten Sie dies zum Beispiel:
def firstVowel(s: String) = s.foldLeft(None: Option[Char]) {
case (None, char) => if ("aeiou" contains char.toLower) Some(char) else None
case (vowel, _) => vowel
}
Für die Referenz ist dies das, was Scala 2.7 Spec (15. März 2009) über die Typ -Zuschreibung zu sagen hat:
Expr1 ::= ...
| PostfixExpr Ascription
Ascription ::= ‘:’ InfixType
| ‘:’ Annotation {Annotation}
| ‘:’ ‘_’ ‘*’
Andere Tipps
Eine Möglichkeit besteht darin, wenn das Zeug für Netzwerk- und Serienprotokollebene, dann Folgendes folgendermaßen:
val x = 2 : Byte
ist weitaus sauberer als
val x = 2.asInstanceOf[Byte]
Die zweite Form ist auch eine Laufzeitumwandlung (nicht vom Compiler behandelt) und könnte zu interessanten Over/Under -Low -Bedingungen führen.
Ich verwende Typ -Zuschreibung zum Papier über Löchern in Scalas Typinferenz. Falten Sie beispielsweise über eine Sammlung vom Typ A ein anfängliches Element vom Typ B und eine Funktion (b, a) = B, mit der die Elemente der Sammlung in das Anfangselement falten. Der tatsächliche Wert des Typs B wird aus dem Typ des Anfangselements abgeleitet. Da NIL die Liste [nichts] erweitert, verursacht die Verwendung als ursprüngliches Element Probleme:
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)
Alternativ können Sie nur die Liste verwenden.
scala> x.foldLeft(List.empty[Int])( (acc,elem) => elem::acc )
res3: List[Int] = List(4, 3, 2, 1)
bearbeiten: list.eMpty [a] wird als implementiert als
override def empty[A]: List[A] = Nil
Dies ist effektiv eine ausführlichere Form von NIL: Liste [a
Du wirst vielleicht finden Dieser Thread Illuminierend, wenn auch etwas verwickelt, um zu folgen. Das Wichtigste ist zu beachten, dass Sie dem Typ -Checker Einschränkungen hinzufügen. Es gibt Ihnen etwas mehr Kontrolle darüber, was diese Kompilierungsphase tut.
Geben Sie Inferenz ein: Wir können explizit einen Namen von etwas im Quellcode geben, der als Typ -Inferenz bezeichnet wird (obwohl in einigen außergewöhnlichen Fällen erforderlich.)
Typenzuschreibung: Wenn Sie sich explizit über die Art von etwas befassen, wird als Typ -Zuschreibung bezeichnet. Welchen Unterschied kann es ausmachen?
Ex: Val x = 2: Byte
Siehe auch: 1. Wir können unseren Funktionen explizit Rückgabetyp geben
def t1 : Option[Option[String]] = Some(None)
> t1: Option[Option[String]]
Eine andere Möglichkeit, dies zu erklären, könnte sein:
def t2 = Some(None: Option[String])
> t2: Some[Option[String]]
Hier gaben wir nicht Option[Option[String]]
Rückgabetyp explizit und Compiler schließte ihn ab als Some[Option[String]]
. Warum Some[Option[String]]
liegt daran, dass wir in der Definition Typ -Zuschreibung verwendet haben.
Eine andere Möglichkeit, die gleiche Definition zu verwenden, ist:
def t3 = Some(None)
> t3: Some[None.type]
Diesmal haben wir dem Compiler nichts explizit erzählt (weder dieser Defi). Und es leitete unsere Definition als einige [keine.typ