Scala:如何确定类型是否可为空
关于Scala中的可空类型,我有两个问题:Scala:如何确定类型是否可为空,scala,nullable,Scala,Nullable,关于Scala中的可空类型,我有两个问题: 假设我想定义一个新类:classmyclass[T](x:T),我想确保T可以为空。我该怎么做 我想编写一个函数def myFunc(x:T)(不是作为上一个问题的一部分),如果T可为空,我想执行一件事,如果不可为空,则执行另一件事。与前面的问题不同的是,这里我不想限制t,而是想知道它是否可以为null。我该怎么做 在scala中,扩展AnyRef(相当于Object)的所有类型都可以为空。不过,大多数scala社区都避免使用空值,并且倾向于通过使用选
classmyclass[T](x:T)
,我想确保T
可以为空。我该怎么做def myFunc(x:T)
(不是作为上一个问题的一部分),如果T
可为空,我想执行一件事,如果不可为空,则执行另一件事。与前面的问题不同的是,这里我不想限制t
,而是想知道它是否可以为null。我该怎么做在scala中,扩展
AnyRef
(相当于Object
)的所有类型都可以为空。不过,大多数scala社区都避免使用空值,并且倾向于通过使用选项表示值的存在/不存在来更加明确。在scala中,扩展AnyRef
(相当于对象)的所有类型都可以为空。大多数scala社区都避免使用空值,并且倾向于更明确地使用选项表示值的存在/不存在,即使我们在scala
中不使用null
,通常(有利于选项
)可以强制函数使用空值参数
def f[T <: AnyRef](x: T) = ???
def[T即使我们在Scala
中不使用null
,但通常(为了支持选项
),您可以强制函数使用null参数
def f[T <: AnyRef](x: T) = ???
def[T1.使用>:Null:Null1.使用>:Null:Null“Nullable”表示它是AnyRef
的子类(而不是Nothing
),因此,您可以强制执行MyClass
只接受可为Null的实例,如下所示:
case class MyClass[T <: AnyRef](t: T)
MyClass("hey")
MyClass[String](null)
MyClass(null)
// MyClass[Int](3) won't compile, because `Int` is primitive
如果您尝试在Any
上使用myFunc
,这将无法编译,因为编译器将无法确定它是AnyRef
还是AnyVal
,这两个隐式方法将冲突。这样,就可以确保在编译时不会意外地在Any
上使用myFunc
“Nullable”表示它是AnyRef
的子类(而不是Nothing
),因此,您可以强制执行MyClass
只接受可为null的实例,如下所示:
case class MyClass[T <: AnyRef](t: T)
MyClass("hey")
MyClass[String](null)
MyClass(null)
// MyClass[Int](3) won't compile, because `Int` is primitive
如果您尝试在Any
上使用myFunc
,这将无法编译,因为编译器将无法确定它是AnyRef
还是AnyVal
,这两个隐式方法将冲突。这样,就可以确保在编译时不会意外地在Any
上使用myFunc
在编译时无法确定其可空性。注意,这通常是不够的-T
还必须是可空的Null
的超类型(因为Nothing
不可空)。虽然在您具有传递类型的值的情况下,这可能并不重要。@Vladimitmaveev Good catch!如果签名类似于def,则实际上可能很重要[T T=?
,因为如果可以区分某物和无
,则可以在无
情况下跳过x
的计算,而不会引发任何运行时异常。请注意,这在一般情况下是不够的-T
还必须是Null
的超类型才能为Null(因为Nothing
不可为null)。虽然在您有传递类型的值的情况下,这可能并不重要。@VladimirMatveev捕捉得好!如果签名类似于def[T],那么它实际上可能很重要=???
,因为如果可以区分某物和无
,则可以跳过无
情况下的x
计算,而不会引发任何运行时异常。可为空[any](3)
返回true
,这是故意的吗?不,我想我在那里使用了一个不正确的运算符,应该是&&
而不是|
固定的。可以为空[Any](3)
返回true
,这是故意的吗?不,我想我在那里使用了一个不正确的运算符,应该是&
而不是|
固定的。
sealed trait Nullability[-T]
case object Nullable extends Nullability[AnyRef] {
def isNull(t: Any): Boolean = t == null
}
case object NotNullable extends Nullability[AnyVal]
object Nullability {
implicit def anyRefIsNullable[T <: AnyRef]: Nullability[T] = Nullable
implicit def anyValIsNotNullable[T <: AnyVal]: Nullability[T] = NotNullable
}
def myFunc[T](t: T)(implicit nullability: Nullability[T]): Unit = {
nullability match {
case Nullable =>
if (t == null) {
println("that's a null")
} else {
println("that's a non-null object: " + t)
}
case NotNullable => println("That's an AnyVal: " + t)
}
}
myFunc("hello")
myFunc(null)
myFunc(42)
// outputs:
// that's a non-null object: hello
// that's a null
// That's an AnyVal: 42