2010-01-18 36 views
63

規範中沒有太多關於類型歸屬的信息,當然也沒有關於其目的的任何內容。除了「通過可變參數工作」之外,我會用什麼類型歸屬?下面是使用它的語法和效果的一些scala REPL。斯卡拉類型歸屬的目的是什麼?

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 

回答

66

類型歸屬只是告訴編譯器從所有可能的有效類型中,期望從表達式中找出什麼類型。

A型是有效的,如果它尊重現有的限制,諸如方差和類型聲明,它要麼是所述類型中的一種的表達它適用於「」,或者有適用的範圍轉換。

因此,java.lang.String extends java.lang.Object,因此任何String也是Object。在你的例子中,你聲明你希望表達式s被視爲Object,而不是String。由於不存在限制,所需類型爲s,因此它可以工作。

現在,你爲什麼要這樣做?試想一下:

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) 

你也按類型ascripting sss聲明中的固定這一點,或者你也可以聲明ss的類型爲Set[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 
} 

對於參考,這是斯卡拉2.7規範(2009年3月15日草案)有什麼看法類型歸屬:

Expr1 ::= ... 
     | PostfixExpr Ascription 

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

一種可能性是,當網絡串行協議層次的東西,則這一點:

val x = 2 : Byte 

遠比

val x = 2.asInstanceOf[Byte] 
吸塵器

第二種形式也是運行時轉換(不由編譯器處理),並可能導致一些有趣的上溢/下溢條件。

+1

呃,學到了一些新東西。我做了一個不幸的數量的網絡協議的東西。很高興知道! – 2010-01-26 03:50:46

+10

爲什麼不使用日常語法? 'val x:Byte = 2' – Jerry101 2015-02-02 22:09:06

0

您可能會發現this thread照明,如果有點複雜跟隨。需要注意的重要一點是,您正在向類型檢查器添加約束提示 - 它使您可以更多地控制編譯階段正在執行的操作。

+0

:)我在這裏轉發了我的問題,所以它會被保留;我選擇的答案是那個線程中最清楚的答案 – davetron5000 2010-01-25 02:04:01

+1

「Page not found」請更新鏈接 – samthebest 2015-02-23 20:50:43

+0

對不起,剛纔看到這個。完成。 – 2017-04-28 06:09:03

0

我在Scala的類型推斷中使用類型歸屬法來對紙張進行過孔。例如,foldLeft覆蓋類型A的集合,其中包含類型B的初始元素和函數(B,A)=> B,用於將集合的元素摺疊到初始元素中。類型B的實際值是從初始元素的類型推斷出來的。由於無擴展列表[沒什麼],用它作爲初始元素會導致問題:

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) 

或者,你可以只使用,而不是無List.empty [INT]:列表[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 

(source)

這實際上是零的一個更詳細的形式:列表[A]

+0

爲什麼不''x.foldLeft [List [Int]](Nil)((acc,elem)=> elem :: acc)'? – 2017-05-30 19:24:37

0

類型推斷:我們可以跳過顯式給出源代碼中的類型名稱,稱爲類型推斷(雖然在一些特殊情況下是需要的。)

類型歸屬:明確某種類型的東西稱爲類型歸屬。 它可以做什麼差異?

例如:VAL X = 2:字節

還看到: 1.我們可以明確地給予退貨類型我們的功能

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

> t1: Option[Option[String]] 

本聲明的另一種方式可以是:

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

這裏我們沒有明確給出Option[Option[String]]返回類型,編譯器推斷它爲Some[Option[String]]。 爲什麼Some[Option[String]]是因爲我們在定義中使用了類型歸屬。

  • 我們可以使用相同的定義另一種方法是:

    def t3 = Some(None)

    > t3: Some[None.type]

  • 這個時候,我們並沒有明確告訴編譯器任何東西(既不defi)。它推斷我們的定義爲一些[None.type]