Question

I want to create factory object with apply method defined that would create underlying case class - here is a sample code

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) {
}

The problem is that apply method in the object and case class's constructor have the same parameter list. So compiler gives me this error:

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

Is there some workaround for this problem?

Thanks a lot

Was it helpful?

Solution 3

One possibility would be to hide (a bit) the class from your users:

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
  )
}

This way there is no conflict and you still can pattern match on DeptEntry.Value if you need. It depends on your use case if this solution is convenient or not. If you want that the trait has the proper vals, you can declare it as

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

and the fields in the case class will override them.

OTHER TIPS

Declare the case class 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) {
}

This is according to Iulian Dragos commenting on SI-844

When you create a case class, the Scala compiler automatically generates a companion object with an apply method for you. This apply method has the same parameters as the case class's constructor. This is why you get this compiler error. The fact that you can't overwrite it ensures that stuff like that holds:

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

Try removing the case from the class definition and write the companion object's apply (and unapply if you need extraction) yourself (and toString, equals and hashCode in the class itself if needed).

You could make DeptEntry a "normal" (not case class) class. Or you can use a Method with a different name in the Object. (e.g. DeptEntry.lowerCase(...))

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top