【问题标题】:Check the runtime type of Scala class instance检查 Scala 类实例的运行时类型
【发布时间】:2022-01-27 05:03:08
【问题描述】:

如果我运行以下代码,则会出现错误:

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")
        }

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

【问题讨论】:

    标签: scala class


    【解决方案1】:

    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()
    }
    

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

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

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


    无论如何,这是你两天内第四次提出一个显示不良做法和单一代码的问题。

    我的建议:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-02
      • 2017-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多