Scala: cast an object and assign it to a variable

时间:2015-09-30 23:18:19

标签: java scala casting instanceof

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!

2 个答案:

答案 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