在Scala中将Null作为参数默认值会产生类型不匹配错误

时间:2019-02-28 21:26:13

标签: scala types null

为了进行超载呼叫,例如

val myPage: DocumentType;
func()
func(myPage)

我写了一个函数:

def func(page: DocumentType = null): Unit = {...}

但收到以下错误:

type mismatch; found : Null(null) required: DocumentType

当我将DocumentType更改为String时,错误消失了。第一个问题:为什么? DocumentType是我无法更改的库中的一种类型,具有以下定义:

type DocumentType <: Document
trait Document

我不希望在每次客户端调用时都将实际参数包装到Option中(例如Option(myPage)),但是是否还有其他选择可以获取相似的参数呢?

2 个答案:

答案 0 :(得分:2)

您可以重载类似的功能

def func(): Unit = { }  // do what you would do with null
def func(page: DocumentType): Unit = { }  // do what you would do with a DocumentType

您可以通过使两者都调用其他私有函数以使其保持DRY,来抽象化实现。然后,您可以拨打func()func(new DocumentType())

原始答案(不太好)

def func(page: DocumentType): Unit = func(Some(page))
def func(page: Option[DocumentType] = None): Unit = ???

表示您无需诉诸null。您将失去干净的API,可以调用

val d = new DocumentType()
func()
func(d)
func(Some(d))
func(None)

答案 1 :(得分:0)

类似的事情应该起作用:

trait Document

trait DocumentFunc {
  // The trick is to tell the compiler that your type can be nullable.
  type DocumentType >: Null <: Document

  def fun(page: DocumentType = None.orNull): Unit = {
    println(page)
  }
}

显然,问题在于,由于仅将上限设置为Document,编译器将拒绝null,因为DocumentType可能会被覆盖为Nothing
并且“显然” null不能在预期Nothing的地方使用。

第一个免责声明:我同意乔尔·伯克利(Joel Berkeley)的观点,您应该避免使用null,我希望他的解决方案。
我只想回答一个真正的问题:“为什么它不起作用”

第二个免责声明:我使用None.orNull只是为了没有明确的null-仅仅是因为我使用的棉短绒禁止使用null
您可以根据需要进行更改。

第三条免责声明: Type Members几乎总是可以更改Type Parameters(通常)更易于使用,并且< em>“ typesafe” 。
Type Members恕我直言,仅在真正需要它们时才使用,例如path dependent types-更多信息可以在here中找到。

第四个免责声明::使用nullUnit (如果有的话,与vars一起使用)是一种症状使用 Scala 作为 Java 的习惯,这(通常)是对该语言的一种不好用法。但是,那只是我的意见。