2010-10-13 77 views
7

我想寫一個類型別名縮短,漂亮和封裝的Scala代碼。 假設我得到了一些集合,它具有作爲一個映射列表的屬性,其值是元組的值。 我的類型會寫如List[Map[Int, (String, String)]]或其他任何更通用的東西,因爲我的應用程序允許它。我可以想象有一個超類型請求Seq[MapLike[Int, Any]]或任何漂浮我的船,具體的子類更具體。斯卡拉類型別名包括伴侶對象[初學]

然後我想爲這個長類型寫一個別名。

class ConcreteClass { 
    type DataType = List[Map[Int, (String, String)]] 
    ... 
} 

然後,我會愉快地使用ConcreteClass#DataType我到處都可以採取一個,並使用它。

現在假設我添加了一個功能

def foo(a : DataType) { ... } 

我想從外面用空列表調用它。 我可以撥打foo(List()),但是當我想將我的基礎類型更改爲Seq的另一種類型時,我必須回來並更改此代碼。此外,它並不是非常明確,這個空列表的目的是作爲DataType。伴侶對象沒有相關的List方法,所以我不能撥打DataType()DataType.empty。當我需要非空列表時,會更加惱人,因爲我必須寫出這個長類型的重要部分。

有沒有什麼辦法可以讓Scala將我的類型理解爲同一件事,包括伴侶對象及其創建者方法,以縮短代碼並對其進行黑箱化? 或者,爲什麼我不應該在第一個這樣做呢?

回答

7

答案是其實很簡單:

class ConcreteClass { 
    type DataType = List[String] 
} 
object ConcreteClass { 
    val DataType = List 
} 
val d = ConcreteClass.DataType.empty 

這使我的代碼來調用ConcreteClass.DataType構建列表,在列表和舉手之勞的所有方法。

非常感謝Oleg的洞察力。他的回答也是最好的情況下,如果你不想委託列舉對ConcreteClass.DataType的任何調用,而是準確地控制你想讓調用者做什麼。

+2

如果你不打算'ConcreteClass'的子類來重載'DataType',你最好把'type'和'val'別名放在伴隨對象中(而不是在類中有一個) )。這是'scala'包對象中的別名的工作原理。 – 2010-10-13 12:22:23

+0

你確實很對。我從現在開始做。謝謝。 – Jean 2010-10-13 12:51:38

+1

除了d是類型List [Nothing] – sourcedelica 2012-07-08 03:01:17

5

這是怎麼回事?

 
class ConcreteClass { 
    type DataType = List[String] 
} 
object DataType { 
    def apply(): ConcreteClass#DataType = Nil 
} 
//... 
val a = DataType() 

+0

This works。謝謝。然而,爲此我必須定義List的每一種方法來做我想做的事情,並且它有點冗長。控制可以調用的內容也是非常好的。感謝你的回答,我想我得到了「可以調用所有列表方法」的通用解決方案:現在發佈它。非常感謝:) – Jean 2010-10-13 04:44:46