【问题标题】:Avoid type cast with type member and sub-typing避免使用类型成员和子类型进行类型转换
【发布时间】:2013-09-28 03:53:15
【问题描述】:

我在路径相关类型和模式匹配方面遇到问题:

trait View[A]

trait Foo {
  type Bar

  def defaultBar: Bar
}
trait Baz extends Foo {
  def view(init: Bar): View[Bar]
}

trait Test {
  val foo: Foo

  def bar: foo.Bar = foo.defaultBar

  def test(): Option[View[foo.Bar]] =
    foo match {
      case b: Baz => Some(b.view(bar))
      case _ => None
    }
}

这会失败,因为 scalac 无法将 foo 识别为 b。因此,它只适用于两种强制转换:

      case b: Baz => Some(b.view(bar.asInstanceOf[b.Bar]).asInstanceOf[View[foo.Bar]])

肯定有一个干净的方法来避免演员表吗?

【问题讨论】:

  • 我不确定,但这样的类型转换不违反路径依赖类型的逻辑吗?那为什么不使用带协方差的类型投影呢?
  • 我不能使用投影,因为基本成员类型太笼统了。这只有在我真正想避免的trait Foo[F <: Foo[F]] { type Bar; def defaultBar: F#Bar } 的圈子里才有效。
  • 您是否缺少来自Baz 的一些代码?在上面的这个示例中,您永远不会将Baz 定义为Bar 的类型。您的测试与 Foo 匹配,但您的代码永远不会使 Baz 成为有效的 Foo
  • @iain BazFoo 的子类型。如果我匹配foo 并发现它是Baz 的一个实例,显然是b eq foo

标签: scala casting path-dependent-type subtyping


【解决方案1】:

不使用投影和将类型限制为defaultBar 是不可能的,我们可以将其覆盖为不相关的数据类型

例如

trait MyFoo extends Foo { override def defaultBar: Int }

【讨论】:

    猜你喜欢
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    • 2020-01-18
    • 1970-01-01
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多