3

私は継承をそれほど頻繁に使用していないので、なぜ機能しないのかよくわかりません。私のプロジェクトでは、次のものがあります。

保護されたメンバーを持つ基本シール クラス:

sealed class TheRoot {
  protected def some: String = "TheRoot"
}

そして、それはいくつかのロジックを持つ子孫です:

final case class Descendant() extends TheRoot {
  def call: Unit = { 
    val self: TheRoot = this
    self.some // <<- throw compilation error
  }
}

上記をコンパイルすると、次のエラーが発生します。

error: method some in class TheRoot cannot be accessed in TheRoot
 Access to protected method some not permitted because
 prefix type TheRoot does not conform to
 class Descendant where the access take place
           self.some

スーパークラスから保護されたメンバーを呼び出す際の問題が何であるかはよくわかりません...しかし、それをコンパニオンオブジェクトにラップすると、より興味深いものになり、問題が魔法のように修正されます:

sealed class TheRoot {
  protected def some: String = "TheRoot"
}

object TheRoot {
  final case class Descendant() extends TheRoot {
    def call: Unit = {
      val self: TheRoot = this
      self.some // <<- NO ERROR!
    }
  }
}


// Exiting paste mode, now interpreting.

defined class TheRoot
defined object TheRoot
4

1 に答える 1

1

ドキュメントに記載されているとおり

保護されたメンバーへのアクセスも、Java よりも少し制限されています。Scala では、保護されたメンバーは、メンバーが定義されているクラスのサブクラスからのみアクセスできます。Java では、このようなアクセスは、同じパッケージ内の他のクラスからも可能です。Scala では、以下で説明するように、この効果を実現する別の方法があるため、protected はそのままにしておくことができます。示されている例は、保護されたアクセスを示しています。

 package p {
  class Super {
    protected def f() { println("f") }
  }
  class Sub extends Super {
    f()
  }
  class Other {
    (new Super).f()  // error: f is not accessible
  }
}

あなたのコードでは、 に変更すれば問題ありませself.somesome

コンパニオン オブジェクトはそのコンパニオン クラスの任意のメンバーにアクセスできるため、Descendantオブ オブジェクトTheRootは の保護されたメソッドにアクセスできます。some

于 2016-06-02T02:18:01.320 に答える