case class 用抽象类型扩展特征
case class extending trait with abstract type
我有几个这样的案例 class:
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
trait 下定义函数,但代码仍然有味道。
- 我需要为每个 属性 添加三次
[T]
我添加
- 我需要显式添加 属性 名称作为额外函数来访问它,就好像在 class.
情况下它只是一个字段一样
现在初始化Title
我需要写
Title(101L, Property("Title"))
而不是
Title(101L, "Title")
出于某种原因,我确信有比我提供的解决方案更优雅、更不容易出错的解决方案。
您不需要 2 个级别,可以将 trait
替换为 abstract class
以利用其构造函数:
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)
这些案例中的每一个都有一个 id
值,这是 Property
class 所要求的,但是由于您希望它们对 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
}
(其余同)
这种方式的优点是可以使用top trait来引用any 属性,例如
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"
我有几个这样的案例 class:
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
trait 下定义函数,但代码仍然有味道。
- 我需要为每个 属性 添加三次
[T]
我添加 - 我需要显式添加 属性 名称作为额外函数来访问它,就好像在 class. 情况下它只是一个字段一样
现在初始化Title
我需要写
Title(101L, Property("Title"))
而不是
Title(101L, "Title")
出于某种原因,我确信有比我提供的解决方案更优雅、更不容易出错的解决方案。
您不需要 2 个级别,可以将 trait
替换为 abstract class
以利用其构造函数:
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)
这些案例中的每一个都有一个 id
值,这是 Property
class 所要求的,但是由于您希望它们对 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
}
(其余同)
这种方式的优点是可以使用top trait来引用any 属性,例如
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"