Frage

I am trying to overload the constructor to a class so that it can accept lists of two different types of objects:

class myClass(){
  var someStrings: List[String]=List[String]()
  println("hello!")

  def this(strings : List[String])={
    this()
    this.someStrings=strings
  }

  def this(ints: List[Int])={
    this()
    this.someStrings=ints.map(x => x.toString)
  }
}

In this case, accept a list of ints or strings, and save a list of strings to the variable someStrings. The code above doesn't work:

error: double definition:
constructor myClass: (strings: List[String])myClass at line 12 and
constructor myClass: (ints: List[Int])myClass at line 17
have same type after erasure: (strings: List)myClass
             def this(ints: List[Int])={
             ^

Is there a better way of doing this in scala? (Other than taking List[Any] and testing the elements)

Thanks!

War es hilfreich?

Lösung

create functions on a companion object which do the construction for you in a typesafe way that can be checked at compile time:

class myClass(){
  var someStrings: List[String]=List[String]()
  println("hello!")
}

object myClass {
  def fromStrings(strings: List[String]) = {
    val c = new myClass
    c.someStrings = strings
  }
  def fromInts(ints: List[Int]) = {
    val c = new myClass
    c.someStrings = ints.map(_.toString)
  }
}

object Usage {
  val c1 = myClass.fromStrings(List("a","b","c"))
  val c2 = myClass.fromInts(List(1,2,3))
}

I would urge you to avoid overloading in general, or checking types at runtime, when you could be checking types at compile-time instead

Andere Tipps

That's what DummyImplicit is for:

def this(strings: List[String])={
  this()
  this.someStrings=strings
}

def this(ints: List[Int])(implicit d: DummyImplicit)={
  this()
  this.someStrings=ints.map(x => x.toString)
}

This makes the erased signatures of constructors (i.e. the ones JVM sees) MyClass(List) and MyClass(List, DummyImplicit), so the overloading is allowed.

However, as @stew says, it could be a better idea to avoid overloading in this case.

In addition to the other answer, another thing you can do is use Arrays. The type information on an array is kept at runtime, so you can do overloading based on the type parameter.

class myClass() {
  var someStrings: Array[String] = Array[String]()
  println("hello!")

  def this(strings: Array[String]) = {
    this()
    this.someStrings = strings
  }

  def this(ints: Array[Int])={
    this()
    this.someStrings = ints.map(x => x.toString)
  }
}

Arrays are much underused in my opinion

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top