根据文档,None
对象旨在“代表不存在的值”。据我所见,它主要用作空Option
。但是你认为将它用于其他目的是一个好主意。例如,在我的库中,我想要一个通用的“Empty”对象,可以为各种缺失值分配,我只是根据需要将“Empty”值隐式转换为我的类型:
// In library:
trait A {
implicit def noneToT1(none: Option[Nothing]): T1 = defaultT1
implicit def noneToT2(none: Option[Nothing]): T2 = defaultT2
def f1: T1
def f2: T2
}
// In the code that uses the library
class EmptyA extends A {
def f1 = None
def f2 = None
}
以这种方式不(错误)使用None
的一个原因是用户希望f1
和f2
分别返回Option[T1]
和Option[T2]
。他们没有。当然,我可能有def f1: Option[T1]
,但在这种情况下,值实际上不是可选的,它们只能有一些默认的空值或实际值,我只想创建默认值“引擎盖下”并有一些统一的方式通过整个库说“默认”或“空”。所以问题是,我应该使用None
来表达这种“默认”还是选择一些自定义类型?现在我正在使用我自己的object Empty
,但感觉有点多余。
修改 为了说明我的问题,我将立即添加我正在使用的代码:
// In library:
trait Empty
object Empty extends Empty
trait A {
implicit def emptyToT1(none: Empty): T1 = defaultT1
implicit def emptyToT2(none: Empty): T2 = defaultT2
def f1: T1
def f2: T2
}
// In the code that uses the library
class EmptyA extends A {
def f1 = Empty
def f2 = Empty
}
class HalfFullA extends A {
def f1 = Empty
def f2 = someValue2
}
class FullA extends A {
def f1 = someValue1
def f2 = someValue2
}
我的问题很简单:使用scala的None
而不是Empty
是个好主意吗?
答案 0 :(得分:7)
我只会使用类型类:
trait WithDefault[T] {
def default: T
}
object WithDefault {
// if T1 is an existing class
implicit val t1Default = new WithDefault[T1] {def default = defaultT1}
}
//if T2 is your own class:
class T2 ...
object T2 {
implicit val withDefault = new WithDefault[T2] {def default = defaultT2}
}
然后方便的地方:
def default[T : WithDefault] = implicitly[WithDefault[T]].default
并使用:
class EmptyA {
def f1 = default[T1]
def f2 = default[T2]
}
更新:为了适应Vilius,可以试试这个:
def default = new WithDefault[Nothing]{def default = error("no default")}
implicit def toDefault[U, T](dummy: WithDefault[U])(implicit withDefault: WithDefault[T]): T = withDefault.default
class EmptyA {
def f1: T1 = default
def f2: T2 = default
}
这有利于OP的原始尝试,因为每个新类都可以定义自己的默认值(以及WithDefault中的其他类),而不是将所有内容都放在特征A
中。
然而,这不起作用。见https://issues.scala-lang.org/browse/SI-2046
解决这个问题:
trait A {
def f1: T1
def f2: T2
implicit def toT1Default(dummy: WithDefault[Nothing]) = toDefault[T1](dummy)
implicit def toT2Default(dummy: WithDefault[Nothing]) = toDefault[T2](dummy)
}
class EmptyA extends A {
def f1 = default
def f2 = default
}
答案 1 :(得分:3)
我认为你应该选择更简单的事情。例如,从您的示例开始并删除无关紧要的东西,我们很快就会到达,
trait A {
def noT1 = defaultT1
def noT2 = defaultT2
def f1: T1
def f2: T2
}
class EmptyA extends A {
def f1 = noT1
def f2 = noT2
}
我真的没有看到添加选项或暗示会增加任何价值,至少除非该问题有其他未说明的背景。
答案 2 :(得分:1)
如果你不能或不想使用继承来定义默认值,我建议保留新对象。将None
重新用于除Some
对应物以外的其他内容似乎是错误的,并不能真正为您节省太多。