【问题标题】:How can I vary the type parameter when dealing with a collection?处理集合时如何改变类型参数?
【发布时间】:2022-01-17 02:10:33
【问题描述】:

假设我有一个具有类型参数 T 的案例类:

case class ProdutOption[T](name: String, value:T)

这个案例类包含在另一个案例类中,例如:

case class Product[T](id: String, options: Set[ProductOption[T]])

对此建模的正确方法是什么?
我希望我的 options 参数能够具有不同类型的 T...我不希望集合中的所有项目都被强制为特定类型。

这种场景可以使用这样的类型参数来建模吗?

【问题讨论】:

  • 如果您不知道Options 有哪些类型,您甚至打算如何使用它们?
  • @LuisMiguelMejíaSuárez 我正在读取 JSON 帖子中发送的值...
  • 这不能回答我的问题。

标签: scala


【解决方案1】:

有点不清楚您到底在寻找什么,但考虑ProductOption 的协方差可能会很有用:

case class ProductOption[+T](name: String, value: T)

这表示如果ST 的超类型,则ProductOption[T]ProductOption[S] 的子类型。

具体而言,这意味着Product[Any] 允许options 成为任何类型的ProductOption

Product("my favorite product", Set(ProductOption[String]("color", "blue"), ProductOption[ShirtSize]("size", ShirtSize.TwoXL))  // type is Product[AnyRef]

【讨论】:

  • 这样,这些选项实际上保持无类型,这并不酷。
【解决方案2】:

一切都取决于您的一组可能的选项类型是关闭(即静态已知)还是打开(直到运行时才知道)以及您希望如何处理这些选项。

如果您可以枚举所有可能的选项,请使用 ADT(代数数据类型):

sealed trait ProductOption[+T] {
  def name: String
  def value: T
}
object ProjectOption {
  case class SomeNumericOption(value: Int) extends ProductOption[Int] {
    def name: String = "numeric"
  }
  case class SomeTextualOption(value: String) extends ProductOption[String] {
    def name: String = "textual"
  }
}

case class Product(id: String, option: Set[ProductOption[_]])

然后您可以使用模式匹配以类型安全的方式处理这些选项。

如果你的选项层次结构未知,那么你应该引入一些方法来处理这个选项到基本特征中,这将不再是sealed

trait ProductOption {
  def name: String

  def processMe(): Whatever = ...
}

case class Product(id: String, option: Set[ProductOption])

processMe 究竟会做什么取决于您的用例。

这是所谓的表达式问题的经典示例。

【讨论】:

    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 2013-12-01
    • 1970-01-01
    相关资源
    最近更新 更多