I want to cast myObject to a specific class and assign it to a variable myTargetObject. I have the following Scala code, but there is error at the cast:
def findResult[T](myObject: T): String = {
var myTargetObject= None
if (myObject.isInstanceOf[myClass1]) {
myTargetObject = myObject.asInstanceOf[myClass1]
} else if (myObject.isInstanceOf[myClass2]) {
myTargetObject = myObject.asInstanceOf[myClass2]
} else (myObject.isInstanceOf[myClass3]) {
myTargetObject = myObject.asInstanceOf[myClass3]
}
}
What should be the right syntax for this purpose? Thank you very much!
答案 0 :(得分:4)
问题是,当您执行var myTargetObject= None
时,它会将类型推断为 Option[Any]
None
,因此尝试将其重新指定为myClassN
将失败。
正确的方法是匹配:
def findResult[T](myObject: T): String = {
myObject match{
case myTargetObject:MyClass1 => {
//Actions for MyClass1
}
case myTargetObject:MyClass2 => {
//Actions for MyClass2
}
case myTargetObject:MyClass3 => {
//Actions for MyClass3
}
case other => {
//Default action
}
}
}
这将允许您将其用作所需类型,同时仍然是完全类型安全的。即使这仍然不太理想,因为你通常不希望行为专门针对调用代码中的每个类。您应该尝试将其重构为使用通用接口,以便可以以相同的方式处理它。
答案 1 :(得分:2)
恕我直言,在Scala中最常用的方法是使用类型类:
class MyClass1(val s: String)
class MyClass2(val s: String)
trait ResultFinder[T] {
def findResult(t: T): String
}
object ResultFinder {
def findResult[T: ResultFinder](t: T): String = implicitly[ResultFinder[T]].findResult(t)
implicit object RFMyClass1 extends ResultFinder[MyClass1] {
override def findResult(t: MyClass1): String = t.s + " of MyClass1"
}
implicit object RFMyClass2 extends ResultFinder[MyClass2] {
override def findResult(t: MyClass2): String = t.s + " of MyClass2"
}
}
REPL会议:
scala> import ResultFinder.findResult
import ResultFinder.findResult
scala> val c1 = new MyClass1("hello")
c1: MyClass1 = MyClass1@39fb3ab6
scala> val c2 = new MyClass2("hello")
c2: MyClass2 = MyClass2@3fee9989
scala> findResult(c1)
res0: String = hello of MyClass1
scala> findResult(c2)
res1: String = hello of MyClass2
此解决方案完全类型安全。没有演员阵容,甚至没有引擎盖。相反,模式匹配技术使用引擎盖下的模型。此解决方案的另一个好处是,它适用于更复杂的类型,如List[MyClass1]
,前提是该范围内有隐式实例。由于类型擦除,模式匹配对List[MyClass1]
不起作用。
PS:我认为您使用myTargetObject
作为 temp 变量,但实际上并不需要它,因为{em>的唯一出路方式 {{ 1}}有意义的是返回findResult
。