[Scala]protectedの挙動

2011年12月27日

protectedの挙動ですが、まず

scalaでは、class とか object のメンバーはデフォルトではすべてパブリックとして定義されます
[scala]object PublicObject {
  val publicVal
  var publicVar
  def publicMethod = 1
}[/scala]
この例では、3つのメンバーは全部publicとして定義される

privateとprotectedは、Javaに良く似ています。
privateはJavaとほぼ同等の動きですが、protectedは劇的に異なります。

一つ目の違いは、protectedは2つの形式を持つことが出来ます。
protectedとprotected[foo]
※fooはclass、package、objectなど

二つ目の違いは、パラメータなしのprotectedは自身とサブクラスからのみ参照可能
[scala]scala> class Class1 {
     | protected def pMethod = "protected"
     | }
defined class Class1
scala> class Class2 {
// Class2はClass1のサブクラスでは無いので、pMethod にはアクセス出来ません。
     | new Class1().pMethod
     | }
<console>:6: error: method pMethod cannot be accessed in Class1
       new Class1().pMethod
                    ^
scala> class Class3 extends Class1 {
// ここがJavaと違うところで、pMethodにはアクセス出来ません。
     | new Class1().pMethod
     | }
<console>:6: error: method pMethod cannot be accessed in Class1
       new Class1().pMethod
                    ^
scala> class Class3 extends Class1 {
// pMethodにアクセス出来ます。
     | pMethod
     | }
defined class Class3[/scala]
パラメータありのprotectedの場合
パラメータに指定されたクラスからは参照できるようになります
[scala]scala> class Class1 {
// protected[Class1] は、privateと同等
     | protected[Class1] def method() = println("hi")
     | method()
     | }
defined class Class1

scala> new Class1()
hi
res0: Class1 = Class1@dc44a6d

// このmethodは、Class1からのみアクセスが出来ます。
scala> class Class2 extends Class1 { method() }
<console>:5: error: not found: value method
       class Class2 extends Class1 { method() }
                                     ^
scala> object Module {
     |   object Inner1 {
     |     protected[Inner1] def innerMethod = println("hi")
     |     protected[Module] def moduleMethod = println("moduleMethod")
     |
     |     object InnerInner {
     |       // InnerInner は Inner1 の中にあるので アクセス可能
     |       def callInner = innerMethod
     |     }
     |   }
     |   // moduleMethod は protected[Module] なので、Module内からはアクセス出来ます。
     |   def callModuleMethod = Inner1.moduleMethod
     |
     |   object Inner2 {
     |     // Inner1.moduleMethod は protected[Module] ですが、Inner2の中なので、moduleMethodはアクセス可能です。
     |     def callModuleMethod = Inner1.moduleMethod
     |   }
     | }
defined module Module
scala> Module.callModuleMethod
moduleMethod
scala> Module.Inner1.InnerInner.callInner
hi
scala> Module.Inner1.innerMethod
<console>:6: error: method innerMethod cannot be accessed in object Module.Inner1
       Module.Inner1.innerMethod
                     ^
scala> Module.Inner1.moduleMethod
<console>:6: error: method moduleMethod cannot be accessed in object Module.Inner1
       Module.Inner1.moduleMethod[/scala]

Scala

Posted by GENDOSU