openlang

怎样继承另一个类里面的类?

你好,

在一个我无法修改代码的包里,类的层次结构如下。

class Outer:
    class Inner(number: Int):
        ???

我想给 Inner 加个方便使用的包装,但因为 Inner 依赖外层实例,目前只做到把它放进外层类的子类里面。

new Outer:
    case class InnerCase(number: Int) extends Inner(number):
        ???

    (new InnerCase(3)).copy() // sample usage

可惜,在多个地方继承 Outer,就意味着每个新子类里都得重复这个方便使用的 case class。为了不反复复制定义,我希望有个类能用于任意 Outer#Inner。我试了下面的办法。

case class InnerCase(number: Int)(owner: Outer) extends owner.Inner(number):
    ???

new Outer:
    host =>
    InnerCase(3)(host).copy()(host)

new Outer:
    host =>
    val instance = InnerCase(4)(host).copy()(host)
    val widened: Inner = instance // line causing trouble

但在需要 Inner 的地方多态地使用 InnerCase 时,会出现这个诊断。

Found: InnerCase
Required: Inner

我还是 Scala 新手,所以觉得应该有更好的办法实现这个目标。想必从类型理论上可以解释为什么直接这样做会违反类型系统。无论如何,很希望有人指点一下继承内部类的“正确”方法。

从英语翻译查看原文

后续讨论 1

顺着彼此的依据读下去
  1. 固定链接

    case class InnerCase(number: Int)(owner: Outer) extends owner.Inner(number): ???

    这在当前的 Scala 3 里根本无法编译。在父类型中引用构造函数参数是不健全的。Scala 3 编译器问题跟踪里的 16270 号问题解释了构造函数参数不安全地出现在父类型中的情况。旧编译器里后续出现的问题,包括你遇到的,经常都源于这种不健全性。

    试试这样安排代码。

    class Outer:
        class Inner(number: Int):
            ???
    
    final class Holder[O <: Outer](val owner: O):
        case class InnerCase(number: Int) extends owner.Inner(number):
            ???
    
    new Outer:
        host =>
        Holder[this.type](this).InnerCase(3).copy()
    
    new Outer:
        host =>
        val holder: Holder[this.type] = Holder(this)
        val instance = holder.InnerCase(4).copy()
        val widened: Inner = instance // works here
    从英语翻译查看原文

同一个问题的其他角度

  1. 比较 Lean4 中的 have 和 let 绑定

    我发现下面两个表达式 以及 行为完全相同。证明定理时也是这样。 它们可以互换吗?区别在哪里?

    回复 3最近活动 lean-4
  2. 初始化以字符串数组为值的 TypeScript Map

    我在创建一个 Map,其中每个条目都保存字符串数组。怎样在一条语句中同时声明类型并完成初始化? 我(天真地)这样试了一下。 结果是下面这个错误。

    回复 2最近活动 typescript
  3. Typescript 可调用函数的约定

    为什么 Typescript 接受我的函数定义,虽然它与接口签名不同,但当我实际调用同一个函数时却报告问题。

    回复 2最近活动 typescript