English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Scala のアクセス修飾子

Scalaのアクセス修飾子はJavaと基本的に同じで、private、protected、publicがあります。

アクセス修飾子が指定されていない場合、デフォルトでは、Scalaオブジェクトのアクセスレベルはすべてpublicです。

Scalaのprivate修飾子はJavaよりも厳格で、ネストされたクラスの場合、外側のクラスはネストされたクラスのプライベートメンバーにアクセスすることができません。

プライベート(Private)メンバー

private キーワードで修飾された、このマークがあるメンバーは、メンバーの定義が含まれているクラスやオブジェクトの内部のみで見える、同じルールが内部クラスにも適用されます。

class Outer{
    class Inner{
    private def f(){ println("f") }
    class InnerMost{
        f() // 正しい
        }
    }
    (new Inner).f() //誤り
}

(new Inner).f()のアクセスが不適切なのは、以下の理由です f Innerクラス内でprivateとして宣言されており、アクセスはInnerクラス内に限られています。

しかしInnerMost内でアクセスする場合 f 問題ありません。なぜなら、このアクセスはInnerクラス内に含まれているからです。

Javaでは、外部クラスが内部クラスのプライベートメンバーにアクセスできるため、これらのアクセスは許可されています。

保護(Protected)メンバー

Scalaでは、保護(Protected)メンバーへのアクセスはJavaよりも厳格です。なぜなら、保護メンバーはそのメンバーが定義されたクラスのサブクラスでのみアクセス可能だからです。一方、Javaではprotectedキーワードで修飾されたメンバーは、そのメンバーが定義されたクラスのサブクラスだけでなく、同じパッケージ内の他のクラスでもアクセス可能です。

package p{
class Super{
    protected def f() { println("f") }
    }
        class Sub extends Super{
            f()
        }
        class Other{
                (new Super).f() //誤り
        }
}

上の例では、Subクラスがfへのアクセスに問題はありません。なぜなら、fはSuperクラスでprotectedとして宣言されており、SubはSuperのサブクラスだからです。逆に、Otherクラスがfへのアクセスは許可されていません。なぜなら、OtherはSuperを継承していないからです。また、Javaではこれも認められます。なぜなら、OtherとSubが同じパッケージにあるからです。

公共(Public)メンバー

Scalaでは、修飾子が指定されていない場合、デフォルトでpublicになります。このメンバーはどこからでもアクセスできます。

class Outer {
   class Inner {
      def f() { println("f") }
      class InnerMost {
         f() // 正しい
      }
   }
   (new Inner).f() // 正しいのはf()がpublicであるためです
}

範囲保護

Scalaでは、アクセス修飾子は限定詞を使用して強調することができます。フォーマットは以下の通りです:

private[x] 
または 
protected[x]

ここでのxは、ある所属するパッケージ、クラス、またはシングルトンオブジェクトを指します。private[x]と書かれた場合、"このメンバーは[...]内のクラスや[...]内のパッケージのクラス及びそのコンパニオンオブジェクトに対してのみアクセス可能で、他のすべてのクラスに対してprivateです。

この技術は、いくつかのパッケージを横断する大規模プロジェクトに非常に有効で、プロジェクトのいくつかのサブパッケージで見えるが、プロジェクトの外部のクライアントには常に見えないものを定義することができます。

package bobsrockets{
    package navigation{
        private[bobsrockets] class Navigator{
         protected[navigation] def useStarChart(){}
         class LegOfJourney{
             private[Navigator] val distance = 100
             }
            private[this] var speed = 200
            }
        }
        package launch{
        import navigation._
        object Vehicle{
        private[launch] val guide = new Navigator
        }
    }
}

上記の例では、クラス Navigator が private[bobsrockets] とマークされているため、このクラスは bobsrockets パッケージに含まれるすべてのクラスとオブジェクトに対して可见です。

例えば、Vehicle オブジェクトから Navigator にアクセスは許可されています。なぜなら、Vehicle オブジェクトは launch パッケージに含まれており、launch パッケージは bobsrockets パッケージに含まれていますが、その逆では、bobsrockets パッケージ外のすべてのコードはクラス Navigator にアクセスできません。