检查 Scala class 实例的运行时类型

Check the runtime type of Scala class instance

如果我运行下面的代码,然后我得到一个错误:

import scala.reflect.ClassTag

class General {
  
}

class SubGeneral extends General {
  def test() = println("tested")
}


class ProGeneral[T <: General: ClassTag] {

  var array = Array.ofDim[T](3, 3)
  
  def funcForSubGeneral(): Unit =
        if (array(0)(0).isInstanceOf[SubGeneral]) then array(0)(0).test()
    
}

那是因为General没有函数test()。 我知道我可以通过模式匹配来解决这个问题。这代替了上面的 funcForSubGeneral() 工作:

def funcForSubGeneral(): Unit =
        array(0)(0) match {
         case s: SubGeneral => s.test()
         case _ => println("nope")
        }

但我想知道是否有可能获取 运行time 类型的数组(0)(0) 并检查它是否是 SubGeneral,如果是这样,那么我调用 test( ), 这应该不会引起问题? 这就是我实际尝试使用 isIntanceOf 的目的。我想省略模式匹配,因为我只对一种类型感兴趣。

isInstanceOf 不会改变任何东西,您需要执行 array(0)(0).asInstanceOf[SubGeneral].test() 才能强制转换。


请注意,转换可能会在运行时失败,因此您需要先检查 if。因此,最终代码如下所示:

if (array(0)(0).isInstanceOf[SubGeneral]) then array(0)(0).asInstanceOf[SubGeneral].test()

但是,由于这很麻烦且容易出错,我们有模式匹配:

array(0)(0) match {
  case subGeneral: SubGeneral => subGeneral.test()
}

但是请注意,类型测试被认为是一种不好的做法;主要是因为它们实际上是 class 检查并且可能会在某些情况下失败。例如:

List("a", "b", "c") match {
  case numbers: List[Int] => numbers.head + 1
}

将在运行时抛出异常,因为由于类型擦除,我们丢失了 [String] 部分并且它仅匹配 List 然后它尝试将第一个元素读取为 Int 这是一个错误。


无论如何,这是您在两天内第四次提出显示不良做法和不合常理的代码的问题。

我的建议:

  1. 我敢打赌您没有按照适当的资源来学习这门语言。相反,您似乎只是想用不同的语法模仿另一种语言 (Python?) 。 - 因此,我鼓励您选择合适的书籍、课程、教程等;正确介绍了该语言及其习语。
  2. 我鼓励你加入比 Whosebug 更适合新手的 official Discord server
  3. 我建议你详细解释你试图解决的元问题(在新问题中或在 Discord 服务器中) ,我很确定有更好更惯用的方法来解决它。