繁体   English   中英

case类用抽象类型扩展trait

[英]case class extending trait with abstract type

我有几个这样的案例类:

case class Size(id: Long, size: Int)

case class Title(id: Long, title: String)
.
.
.

我有10个具有几乎相同的功能。 我决定将它们组合在一个共同的特征之下,这导致了这样的事情:

trait Property[T]{
    val value: T
}

trait PropertyPair[T]{
   val id: Long
   val prop: Property[T]
}

case class Size(id: Long, prop: Property[Int]) extends PropertyPair[Int] {
    def size: Int = prop.value
}

case class Title(id: Long, prop: Property[String]) extends PropertyPair[String] {
    def title: String = prop.value
} 

虽然上面的代码块似乎是一个很好的解决方案,现在我可以在PropertyPair特性下实际定义函数,但代码仍然有气味。

  1. 我需要为我添加的每个属性包含[T]三次
  2. 我需要显式添加属性名作为一个额外的函数来访问它,好像它只是case类中的一个字段。

现在初始化Title我需要写

Title(101L, Property("Title")) 

代替

Title(101L, "Title")

出于某种原因,我确信有一个更优雅,更不容易出错的解决方案,而不是我提供的解决方案。

你不需要2个级别,可以用abstract class替换trait来使用它的构造函数:

sealed abstract class Property[T](val prop: T) {
  val id: Long
}

case class Size(id: Long, size: Int) extends Property[Int](size)
case class Title(id: Long, title: String) extends Property[String](title)

这些情况中的每一个都具有Property类所需的id值,但是如果您希望它们具有prop不同名称,您可以将它们作为prop值传递给Property构造函数。

然后它可以用作

val size = Size(101L, 42)
val title = Title(202L, "Foo")

这是一个简单的解决方案。 对于更一般的情况,我建议你这样做:

sealed trait AnyProperty {
  val id: Long

  type Prop
  val prop: Prop
}

sealed abstract class Property[T](
  val prop: T
) extends AnyProperty {
  type Prop = T
}

(其余的都一样)

这种方法的优点是,您可以使用顶级特征来引用任何属性,例如

def foo[P <: AnyProperty](p: P): Long = p.id
foo(size) // 101L

例如,您可以参考Prop类型成员

def buh[P <: AnyProperty](p: P): P#Prop = p.prop
buh(title) // "Foo"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM