Reputation: 2705
I need to instantiate a different class depending on a the value of a particular argument in my application. Something like:
class x { val z = 5}
class y { val z = 10}
def myClass(input:String): Class[_] = {
input match{
case "x" => x
case "y" => y
}
}
val a = new myClass("x")
Any ideas how to do this or if this is possible? It tried the above code and I get a type mismatch with the output so maybe it's as simple as specifying the output type correctly, which I'm pretty sure I'm not.
Thanks.
Upvotes: 0
Views: 1839
Reputation: 40500
It's not clear what it is you are actually trying to do: on one hand, you are saying that you need to instantiate the class, on the other, your function is declared to return the Class
itself, not an instance.
So, if you are trying to create an instance, something like this would work:
def myClass(input: String): AnyRef = input match {
case "x" => new x
case "y" => new y
}
Note: there are two problems with this function. First, it will throw an exception if input happens to be neither x
nor y
... This is not very nice. It is a better idea to make it return an Option
, and add a default to None, when input isn't matched:
def myClass(input: String): Option[_] = Option(input) collect {
case "x" => new x
case "y" => new y
}
Another problem is that you cannot do very much with the value returned by this function the way it is written, because you don't know what type it has, so, you can't access any of it's members (other than the common stuff like toString
, equals
etc.).
It may be a better idea to define a common trait like the other answer suggests, and narrow down the return type of the function to that trait:
trait Foo { def z: Int }
class x extends Foo { val z = 5 }
class y extends Foo { val z = 10 }
def myClass(input: String): Option[Foo] = Option(input) collect {
case "x" => new x
case "y" => new y
}
Finally, if what you wanted was to actually return the Class
object, and not an instance, then you almost have it, except, you need to add a classOf
keyword (it's still better to make the result optional, in case input does not match):
def myClass(input: String): Option[Class[_]] = Option(input) collect {
case "x" => classOf[x]
case "y" => classOf[y]
}
Or, better, with the type boundary:
def myClass(input: String): Option[Class[_ <: Foo]] = Option(input) collect {
case "x" => classOf[x]
case "y" => classOf[y]
}
Upvotes: 1
Reputation: 1131
You should clarify what you're trying to accomplish because runtime reflection would allow you to do this, but 99.9% of the time it's the wrong way to solve your problems.
You can do something like:
trait A
case class B(value: String) extends A
case class C(value: Int) extends A
def doSomething(input: String): A = input match {
case "x" => B("Wahoo")
case "y" => C(123)
}
Upvotes: 3