81

There's not much info in the spec on what type ascription is, and there certainly isn't anything in there about the purpose for it. Other than "making passing varargs work", what would I use type ascription for? Below is some scala REPL for the syntax and effects of using it.

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
4

5 に答える 5

86

型の帰属は、可能なすべての有効な型から、式から期待される型をコンパイラに伝えるだけです。

型は、分散や型宣言などの既存の制約を尊重する場合に有効であり、適用される式が " is a " である型のいずれかであるか、スコープ内で適用される変換があるかのいずれかです。

したがって、java.lang.String extends java.lang.Object、したがって、 anyStringObjectです。あなたの例では、式をではなくsとして扱いたいと宣言しました。それを妨げる制約はなく、目的の型は a型の 1 つであるため、機能します。ObjectStrings

さて、なぜあなたはそれが欲しいのですか?このことを考慮:

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)

s宣言時に型をスクリプト化することでこれを修正することも、の型を とss宣言することもできます。ssSet[AnyRef]

ただし、型宣言は、識別子に値を割り当てている場合にのみ同じことを実現します。もちろん、コードにワンショット識別子を散らかすことを気にしないのであれば、いつでもできることです。たとえば、次はコンパイルされません。

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

しかし、これは:

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

ここで の代わりに識別子を使用するのはばかげていますNil。代わりに書くこともできますがList[String]()、それが常に選択肢になるとは限りません。たとえば、次のように考えてください。

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

参考までに、これは Scala 2.7 仕様 (2009 年 3 月 15 日ドラフト) が型帰属について述べていることです。

Expr1 ::= ...
        | PostfixExpr Ascription

Ascription ::= ‘:’ InfixType
             | ‘:’ Annotation {Annotation}
             | ‘:’ ‘_’ ‘*’
于 2010-01-18T16:06:35.703 に答える
28

1 つの可能性は、ネットワークおよびシリアル プロトコル レベルのもので、次のようになります。

val x = 2 : Byte

よりもはるかにきれいです

val x = 2.asInstanceOf[Byte]

2 番目の形式もランタイム変換 (コンパイラーによって処理されない) であり、いくつかの興味深いオーバー/アンダーフロー条件につながる可能性があります。

于 2010-01-18T16:18:19.330 に答える
0

私は Scala の型推論の穴を埋めるために型帰属を使用します。たとえば、型 A のコレクションに対する foldLeft は、型 B の初期要素と、コレクションの要素を初期要素に折りたたむために使用される関数 (B, A) => B を取ります。型 B の実際の値は、初期要素の型から推測されます。Nil は List[Nothing] を拡張するため、初期要素として使用すると問題が発生します。

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)

または、Nil:List[Int] の代わりに List.empty[Int] を使用することもできます。

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

編集: List.empty[A] は次のように実装されています

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

(ソース)

これは事実上、Nil:List[A] のより冗長な形式です。

于 2014-04-02T16:33:33.687 に答える
0

従うのが少し複雑な場合は、このスレッドが明るくなることがあります。注意すべき重要なことは、型チェッカーに制約のヒントを追加していることです。これにより、コンパイル フェーズの動作をより細かく制御できます。

于 2010-01-21T03:29:52.450 に答える