我有一个如下所示的案例类:
case class SomeType[T](x: T)
我现在想通过这样的伴侣对象提供一个空的初始化方法:
object SomeType {
def empty = SomeType(???)
}
如何实例化泛型类型?我显然不想将它实例化为null或Nill或Any!还有更好的方法吗?
答案 0 :(得分:3)
您所提问题的问题是SomeType[T]
的值x
类型为T
。 为空应该x
采用什么值?唯一明智的答案是应该是Nothing
,但类型Nothing
无人居住。也就是说,你不能这样做:
def empty[A]: SomeType[A] = SomeType(???)
你不能使x
成为一个名字参数(即=> T
),因为你有一个案例类(即使你可以,也会很愚蠢,因为有人可以这样做):
val st: SomeType[Int] = SomeType.empty //would require T to be covariant
val i = st.x //throws Exception
让我们退后一步,不用x
开始:
sealed trait SomeType[T]
object SomeType {
def empty[A]: SomeType[A] = new SomeType[A] {}
def nonEmpty[A](a: A); SomeType[A] = new SomeType[A] {}
}
如果你正在建模有点像Option
的东西,那么值得思考它应该具备的基本组合器是什么。这是编码Option
的一种方法,例如:
sealed trait MyOption[T] {
def fold[B](n: => B, s: T => B): B //fundamental combinator
//functionality
import MyOption._
final def isEmpty = fold(true, _ => false)
final def flatMap[B](f: A => MyOption[B]): MyOption[B] = fold(empty, f)
final def map[B](f: A => B): MyOption[B] = fold(empty, f andThen nonEmpty)
}
object MyOption {
//These are effectively the constructors
def empty[A]: MyOption[A] = new MyOption[A] {
override final def fold[B](n: => B, s: A => B): B = n
}
def nonEmpty[A](a: A): MyOption[A] = new MyOption[A] {
override final def fold[B](n: => B, s: A => B): B = s(a)
}
}
您可以使其协变并使empty
成为val
:
sealed trait MyOption[+T] {
def fold[B](n: => B, s: T => B): B
}
object MyOption {
val empty: MyOption[Nothing] = new MyOption[Nothing] {
override final def fold[B](n: => B, s: Nothing => B): B = n
}
def nonEmpty[A](a: A): MyOption[A] = new MyOption[A] {
override final def fold[B](n: => B, s: A => B): B = s(a)
}
}
或者如下面的 Yuval 所示,将empty
设为单身:
object MyOption {
object empty extends MyOption[Nothing] {
override final def fold[B](n: => B, s: Nothing => B): B = n
}
def nonEmpty[A](a: A): MyOption[A] = new MyOption[A] {
override final def fold[B](n: => B, s: A => B): B = s(a)
}
}
我通常不喜欢这样做,因为我宁愿使用组合器而不是显式模式匹配,这不太适合重构