4

我想使用定义的应用方法创建工厂对象,该方法将创建基础案例类 - 这是一个示例代码

object DeptEntry {  
  def apply(url: String, fullName: String, address: String, city: String): DeptEntry = {
    new DeptEntry(url.toLowerCase, fullName.toLowerCase, address.toLowerCase, city.toLowerCase)
  }
}

case class DeptEntry private(url: String, fullName: String, address: String, city: String) {
}

问题是对象和案例类的构造函数中的 apply 方法具有相同的参数列表。所以编译器给了我这个错误:

method apply is defined twice
  conflicting symbols both originated in file 'DeptEntry.scala'
case class DeptEntry private(url: String, fullName: String,
       ^

这个问题有一些解决方法吗?

非常感谢

4

4 回答 4

3

声明案例类abstract

object DeptEntry {  
  def apply(url: String, fullName: String, address: String, city: String): DeptEntry = {
    new DeptEntry(url.toLowerCase, fullName.toLowerCase, address.toLowerCase, city.toLowerCase) {}
  }
}

abstract case class DeptEntry private(url: String, fullName: String, address: String, city: String) {
}

这是根据 Iulian Dragos对 SI-844 的评论

于 2014-08-04T08:56:55.650 回答
1

当你创建一个case class时,Scala 编译器会自动为你生成一个带有 apply 方法的伴生对象。此 apply 方法与案例类的构造函数具有相同的参数。这就是您收到此编译器错误的原因。你不能覆盖它的事实确保了这样的东西:

val inputUrl = "MyUrl://blabla"
val DeptEntry(outputUrl, _, _, _) = DeptEntry(inputUrl, "", "", "")
outputUrl == inputUrl 

尝试case从类定义中删除 并自己编写伴随对象的applyunapply如果需要提取)(如果需要toStringequalshashCode可以在类本身中)。

于 2013-07-04T09:19:27.973 回答
0

您可以使 DeptEntry 成为“普通”(不是案例类)类。或者您可以在对象中使用具有不同名称的方法。(例如 DeptEntry.lowerCase(...))

于 2013-07-04T09:19:19.830 回答
0

一种可能性是向您的用户隐藏(一点)该类:

sealed trait DeptEntry
object DeptEntry {
  def apply(url: String, fullName: String,
            address: String, city: String): DeptEntry = // ...

  case class Value protected[DeptEntry](
    url: String, fullName: String, address: String, city: String
  )
}

这样就没有冲突,DeptEntry.Value如果需要,您仍然可以进行模式匹配。此解决方案是否方便取决于您的用例。如果您希望特征具有正确val的 s,则可以将其声明为

sealed trait DeptEntry {
    val url: String
    val fullName: String
    val address: String
    val city: String
}

并且 中的字段case class将覆盖它们。

于 2013-07-04T11:36:57.257 回答