2017-02-05 70 views
1

*因爲我們知道scala數組包含相同類型的數據。但是當我聲明數組爲具有不同數據類型的Scala數組

var a = new Array[Any](3) 

我能夠存儲不同的數據類型。

a(0)=5 
a(1)="hello" 
a(2)=1.5 

怎麼可能?如果它是錯誤的,那麼我們在scala中有什麼選擇來存儲不同的數據類型?*

+1

我認爲這個問題的正確答案太廣泛了。請參閱衆多Scala教程之一 –

+0

您的問題表明您將價值理解爲只有一種獨特的類型。但它不會 - 在使用子類型的語言中,值可以同時成爲多種類型的成員。 –

回答

3

「相同類型」的概念總是取決於一般性級別。在Scala中,通用性的級別由正式類型決定。

3和7「同一類型」?如果我們寫...

val a : Int = 3 
val b : Int = 7 

然後他們的相同類型Int。但是,如果我們定義位長度的限制Int類型(我們是非常歡迎的斯卡拉做的),我們可以寫

val a : Int2 = 3 
val b : Int3 = 7 

,他們似乎不再是同一類型的!

如果我們定義一個繼承層次

trait Animal; 
class Dog extends Animal; 
class Frog extends Animal; 

然後做DogFrog具有相同類型的?如果我們寫

val d : Dog = new Dog 
val f : Frog = new Frog 

那麼它看起來像答案是否定的。但如果我們寫

val d : Animal = new Dog 
val f : Animal = new Frog 

然後他們看起來像他們有相同的類型。與一致的,如果我聲明一樣

val arr : Array[Dog] = Array.ofDim[Dog](5) 

一個數組,那麼我不能把一隻青蛙,因爲青蛙是不是狗。但是,如果我宣佈了類似的陣列

val arr : Array[Animal] = Array.ofDim[Animal](5) 

那當然既青蛙和狗可以在裏面去,因爲在Animal一般性的水平,無論是青蛙和狗都具有相同的類型。

在斯卡拉Any是所有其他類型派生的基本類型。因此,在通用性水平非常高的情況下,5,"hello"1.5都具有相同類型Any,就像通常的高級別FrogDog具有相同類型Animal一樣。所以將5,"hello"1.5放入Array[Any]是沒有問題的。

1

是的,你是對的scala array,你確實存儲在這裏的數據same type。看到這個例子:

scala> val a = Array(5,"hello",1.5) 
a: Array[Any] = Array(5, hello, 1.5) 

我們沒有看到包含integerstringdouble數組被創建。我們看到創建了一個array of Any。在array creation期間,scala編譯器尋找nearest common supertype in hierarchy來滿足Array的屬性,它可以是hold elements of same type only。在這種情況下,Any是所有類的超類型,滿足條件。而且,如果編譯器找不到公共超類型,則數組創建將失敗。

需要注意的是,它不只是爲陣,這同樣適用於存儲其他collectionssame types。對於如:列出

scala> val list = List(5,"hello",1.5) 
list: List[Any] = List(5, hello, 1.5) 

什麼是我們在斯卡拉的選項來存儲不同類型的數據?

正如您所看到的,我們無法在ListArray這裏同時使用preserve the type of elements。所有的元素都被存儲爲Any。對於保留類型的元素,並將它們存儲起來,斯卡拉爲我們提供了Tuple

scala> val tuple = (5,"hello",1.5) 
tuple: (Int, String, Double) = (5,hello,1.5) 
0

正如其他人回答爲什麼Array[Any]可以有類型的字符串,布爾值,詮釋等等元素讓我回答這個問題的下方部分

如果是錯誤的,那麼什麼是我們必須在Scala中存儲 不同的數據類型的選項?*

最明顯的答案是Shapeless library。 Shapeless支持稱爲HList的高級數據結構,使用它可以將不同類型的類型存儲在列表中,而不會丟失類型信息。

例如參見下面的代碼段

scala> import shapeless.{::, HList, HNil} 
import shapeless.{$colon$colon, HList, HNil} 

scala> val list = 1 :: "a" :: true :: HNil 
list: shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]]] = 1 :: a :: true :: HNil 

scala> list.head 
res0: Int = 1 // notice the type of the element is Int and not Any 

scala> list.tail.head 
res1: String = a 

scala> list.tail.tail.head 
res2: Boolean = true 

在上面的代碼你有HList類型的不同的地址類型IntStringBoolean三個元件一個VAL list。當您檢索HList的元素時,元素的原始類型將被保留,並且您不會像Array的情況那樣獲得像Any這樣的通用類型。這是可能的,因爲HList不僅存儲數據,而且還存儲元素的類型信息,並在檢索時正確地轉換它們。

相關問題