2010-10-13 73 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