根据评论者(Miles和m-z)的反馈更新了我的问题:
我通过姓名或年龄找到重复的“值”。
sealed trait DuplicateResult
case class DuplicatesByName(name: String, people: Set[String]) extends DuplicateResult
case class DuplicatesByAge(age: Int, people: Set[String]) extends DuplicateResult
根据姓名或年龄,返回类型必须不同:
sealed trait QueryByDuplicate {
type DuplicateResultType
}
case class Name(name: String) extends QueryByDuplicate {
override type DuplicateResultType = DuplicatesByName
}
case class Age(age: Int) extends QueryByDuplicate {
override type DuplicateResultType = DuplicatesByAge
}
然后,我定义了一个编译并运行的函数:
def findDupes(x: QueryByDuplicate): DuplicateResult = x match {
case Name(n) => DuplicatesByName(n, Set("1", "2"))
case Age(a) => DuplicatesByAge(a, Set("42"))
}
scala> findDupes(Name("kevin"))
res0: DuplicateResult = DuplicatesByName(kevin,Set(1, 2))
scala> findDupes(Age(77))
res1: DuplicateResult = DuplicatesByAge(77,Set(42))
然而,type DuplicateResultType
似乎很弱,因为我可以在那里添加任何类型。
请批评并改进我的实施。
答案 0 :(得分:0)
选项1:结果类型信息在您的版本中丢失,因为调用者无法影响findDupes
的固定结果类型。您可以使用泛型,以便调用者重新获得此控件:
sealed trait QueryByDuplicate[T <: DuplicateResult]
case class Name(name: String) extends QueryByDuplicate[DuplicatesByName]
case class Age(age: Int) extends QueryByDuplicate[DuplicatesByAge]
def findDupes[T <: DuplicateResult](x: QueryByDuplicate[T]): T = x match {
case Name(n) => DuplicatesByName(n, Set("1", "2"))
case Age(a) => DuplicatesByAge(a, Set("42"))
}
val dupes: DuplicatesByName = findDupes(Name("kevin"))
选项2:既然你也要求批评,我不认为你设计的方式是一种好的做法。有几个定义查询的类,以及不同位置的每个类的实现列表,难以维护。你可以使用好的旧多态:
sealed trait QueryByDuplicate[T <: DuplicateResult] {
def findDupes: T
}
class Name(name: String) extends QueryByDuplicate[DuplicatesByName] {
override def findDupes: DuplicatesByName = DuplicatesByName(name, Set("1", "2"))
}
class Age(age: Int) extends QueryByDuplicate[DuplicatesByAge] {
override def findDupes: DuplicatesByAge = DuplicatesByAge(age, Set("42"))
}
val dupes: DuplicatesByName = new Name("kevin").findDupes
这就是你可能会用Java做的。有时候,即使我们有新玩具,最好还是坚持旧的方式。
选项3:谈论instanceOf
,这也有效:
sealed trait QueryByDuplicate {
type DuplicateResultType
}
case class Name(name: String) extends QueryByDuplicate {
override type DuplicateResultType = DuplicatesByName
}
case class Age(age: Int) extends QueryByDuplicate {
override type DuplicateResultType = DuplicatesByAge
}
def findDupes(x: QueryByDuplicate): x.DuplicateResultType = x match {
case Name(n) => DuplicatesByName(n, Set("1", "2")).asInstanceOf[x.DuplicateResultType]
case Age(a) => DuplicatesByAge(a, Set("42")).asInstanceOf[x.DuplicateResultType]
}
val dupes: DuplicatesByName = findDupes(Name("kevin"))
findDupes()
在字节码中的返回类型为Object
,但Scala足够聪明,可以推断出正确的类型。