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를 상속하면 새 서브클래스마다 편의용 케이스 클래스를 반복해서 넣어야 한다는 거예요. 정의를 계속 복사하지 않도록 임의의 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