【问题标题】:Scala type alias including companion object [beginner]Scala 类型别名,包括伴随对象 [初学者]
【发布时间】:2011-04-24 15:35:30
【问题描述】:

我想写一个类型别名来缩短、漂亮和封装的 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 将我的类型理解为相同的东西,包括伴随对象及其创建者方法,以缩短代码并将其黑盒化? 或者,我为什么不应该首先这样做?

【问题讨论】:

    标签: scala encapsulation type-alias companion-object


    【解决方案1】:

    答案其实很简单:

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

    这使我的代码能够调用 ConcreteClass.DataType 以使用 List 中的所有方法构建列表,并且不费吹灰之力。

    非常感谢 Oleg 的洞察力。如果您不想将任何对 ConcreteClass.DataType 的调用委托给 List,但要精确控制您希望允许调用者执行的操作,他的回答也是最好的。

    【讨论】:

    • 如果您不打算将ConcreteClass 的子类覆盖DataType,则最好将typeval 别名都放在伴随对象中(而不是在班上)。这就是 scala 包对象中的别名的工作方式。
    • 除了 d 是类型 List[Nothing]
    • 我也在尝试这样做,但我正在寻找某种方式来编写 val d = DataType(arg1, arg2) 并且类型系统将其称为 DataType 但基础类型是 List
    【解决方案2】:

    这个呢?

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

    【讨论】:

    • 这行得通。谢谢。但是,有了这个,我必须定义 List 的每一个方法来做我想做的事,这有点冗长。控制可以调用的内容也非常好。感谢您的回答,我想我得到了“可以调用所有列表方法”的通用解决方案:现在发布。非常感谢:)
    猜你喜欢
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多