19.0514

可視性修飾子(Visibility Modifiers) とは、
  プロパティ や メソッド などに、アクセスレベルを決定する キーワード です。
    / よく、「プロパティ が、見える/見えない」 のような言い方もします。
まず、リファレンス の ページは、こちらです。
Visibility Modifier
   (英語のリファレンス で、method/メソッド という言葉は使われていませんが、
    「classに所属する関数:メソッド」 は、私は区別した方がいいと思いますが。)
可視性修飾子
いきなり、リファレンスを紹介したのは、
私には、完全には分からない所があるので、その部分を調べるための参考にと思って、
紹介しまた。

特に、internal は、IntelliJ だったら、その「プロジェクト」 に、関係はある
ということぐらいしか分かりません。

  ただ言えるのは(IntelliJ について)、

  ー ここから、「Kotlinプログラミング 5ページ」 より引用
  プロジェクト(project)には、あなたのプログラムの全部のソースコードと、
  依存性や構成についての情報が含まれる。
  1個のプロジェクトは、1個以上の モジュール(module)に分割できる。
  モジュールは、いわば「サブプロジェクト」のようなもので、
  デフォルトでは、新しいプロジェクトは モジュール を1個だけ持つことになる
  (シングルモジュール)。

  最初の単純なプロジェクトに 必要なのは、それだけなのだ。
  -引用、ここまで

  つまり、
    internal:同じモジュール内から見える
      この意味は、
        外の モジュールからは、見えない!ようにする.
      という事であり、
      もともと、同じモジュール内 であれば、
      (特に、アクセスを拒むものがなければ)
      同じモジュール内 では、デフォルトで、お互いに見える状態である
      (デフォルトで、アクセス は、public で、外から見える状態)
      という事になり、新たなモジュールを、作らない限りは、
      この、internalキーワード は、気にしなくてもよい
      ということになるはずです。
      なので、入門レベルのAndroidプログラミング に、関しては、
      気にしなくても、多分、OK だと思われます。
      
また、ここで気を付けるのは、
  アクセス制限を、考える時
    スコープ
    同じファイルか?
    同じフォルダか?(IntelliJ なら、自動でやってくれるでしょう)
    パッケージ
  まだ、あるかもしれませんが?
こんなことも、一緒に考慮する必要があります。


リファレンス の、コード を、見て基本的な理解をする
  1. private
  2. protected
  3. internal
  4. public
リファレンスのコードは、こんなコードです
カラー版

リファレンスのコード を、考える前に、それぞれの、修飾子 の 定義を確認しておきましょう。
  ー 「Kotlin イン アクション(96ページ)」 より引用
ポップアップします!

修飾子 クラスメンバ トップレベルの宣言
private クラス内からのみ参照可能 ファイル内からのみ参照可能
protected サブクラスから参照可能 使用できません
internal  モジュール内からのみ参照可能   モジュール内からのみ参照可能 
 public(デフォルト どこからも参照可能 どこからも参照可能



open class ⇒ SubClass
protectedプロパティ の、override


まず、「トップレベル」 の意味を確認しておきましょう。
protectedキーワード は、「トップレベルの宣言が出来ない」 とありますが、
こんなコードで、確認しました
つまり、「(一番外にある)class に、protectedキーワード は、付けられない」 という事になります。


Outerクラス を、継承したSubclass から、見える/見えない?
これに関しては、リファレンスのこの部分 に関して、考えてみます
ポップアップします!
そして、こんなコードで、検証しました
// a は見えない18~23行目)
19行目:
  ここでは、(無名の)Outerクラスのインスタンス を作って(Outer())、
  2行目の、privateな、変数a に、アクセスしています。
  ここでの、a は、「クラスメンバ/classMember(フィールド/プロパティ または、メソッド)」 です。
  先ほど示しました 「修飾子 の 定義」 を、確認しますと、
  a は、Outerクラス(1~11行目)の 中 からしか見えない です。
  よって、アクセス出来ないので、IntelliJ が、 を、引いています。
21行目:
  open class Outer(open は継承のためのキーワード)を、継承した、
  Subclass の、インスタンス Subclass() を使って、変数a に、アクセスしてますが、
  19行目 と、同様、a は、見えません。

Subclass/SubClass とは、よく リファレンス などで、 「子供クラス」 を、表すために、よく使われます。 「親クラス」 の場合は、   Superclass/SuperClass で、表されます。
23行目:
  13行目 で、
  privateキーワード を、
    トップレベルで宣言(class に、private で飾る/を付ける)
  して、TopLevelPrivateClass を、定義していますが、
  そのインスタンス、
    TopLevelPrivateClass()
  を、生成して/作って、
    同じファイル内から、アクセス可能
  を、検証してます。
  定義通り、アクセス出来ています(インスタンス作成可能)。
   (この使い方は、Java には、ありません)
  また、ここでは、
    そのプロパティ である、x
  に、アクセスして、文字列"x" を、
  変数topLevelPrivateClass へ、代入しています。
  また、
    同じファイル(VisibilityTest_01.kt)だから、アクセスできるのであって、
    他のファイルから は、アクセス出来ない!ことが、ポイント
  です。

// b, c, d は見える24~36行目)
25行目:
  protectedな、Outerクラスのプロパティb に、アクセスするために(3行目)、
  Outerクラスの 無名インスタンス(変数に代入していないので、無名なのです)、
    Outer()
  を、作成して、b に、アクセスしようとしていますが、
    クラスメンバb には、
    サブクラス/Subクラス/子供クラス からしかアクセス出来ない!
  ので、IntelliJ が、 を、引いています。
27行目:
  25行目 と違って、ここでは、
  Subclass(Subクラス/継承したクラス)の、無名インスタンスSubclass() で、
  Outerクラス の、プロパティb に、アクセスしようとしています。
    protectedbには、
    Subクラス からなら アクセス出来る
  というルールにより、アクセスに成功してます。

29, 31 行目:
  Outerクラスの、プロパティc(4行目)に、共にアクセスしようとしています。
  クラスメンバc の、アクセス制限は、internal ですから、
    モジュール内からだけアクセス出来る
  というルールです。
  この場合(新しいモジュールは作成していないし、またそこまで考えなくても)、同じファイル内 なので、
  当然、アクセス可能です。
  ここでは、Outerクラス と、Subclass の 無名インスタンス
  (Outer()、Subclass()
  を使って、アクセスしています。

33, 35 行目:
  Outerクラス の、プロパティd(5行目)に、共に、アクセスしようとしています。
  クラスメンバd の、アクセス修飾子 は、public ということになります。
  public というのは、何もつけなくても、デフォルトでの、アクセス制限になり、
    どこからでも、見える
  というルールで、もちろん、アクセス出来ています。
  ただ、「どこからでも見える」 と言っても、
    自前の/自作の class によるものであれば、
    「同じモジュールではなく」、同じプロジェクトに、存在する必要があるでしょう。
  また、
    import文(パッケージ指定)が、必要 な場合
  も、考えられます。


protected が、継承したclass で、override された場合
// b は、protected
38行目:
  ここでは、
    override val b = 5
  というコードで、Subclass(17~39行目)の、プロパティ として、
  変数b が、オーバーライド/override されていますが、
    b は、アクセス制限 としてprotected が、引き継がれている
  と、コメントで言っています。
  そこで、
    override されても、protected を、引き継ぐ
  ことを、確認するために、
    Subclassクラス を、継承して、
    SubSubクラス(41~47行目)を、作成して、
    そのクラスから、protected が、継承されている
  を、確認しています。
  41行目で、
    Subclassクラス を、継承して、SubSubクラス を、定義しています。
  42行目:
    ここでは、SubSubクラス の、親クラス/スーパークラス の、無名インスタンスSubclass()
    を、作成して、Subclassクラス の、メンバ/プロパティ b(38行目)
    に、アクセスしようとしていますが、
   (25行目と同様に)Subclassクラスインスタンス では、アクセス出来ません。
  44行目:
    ただ、継承したSubSubクラスインスタンス からは(27行目のように)、
    アクセス出来るはずです。
      val subClassB2: Int = SubSub().b
    で、アクセスに成功し、その値 5 を、変数subClassB2 に、代入しています。
  よって、
    override された、メンバ(プロパティ と メソッド) は、protected を、引き継ぐ
  ことが、確認できました。


ネストされたクラス は、サブクラス から見えるのか
これに関しては、リファレンスの、この部分 を、考えてみます
ポップアップします!
そして、こんなコードで、検証しました
14行目:
  まず、
    class の中にある class
  について、考えてみる必要がありそうです。

  ここは、Java とは、違う部分があるので、言及した方がいいと思います。
      -Kotlin イン アクション 100ページ より
    Kotlin の明示的な修飾子の付かない ネストされたクラス は、
    Java の staticなネストされたクラス と同等です。
      -引用ここまで
  (このコードのように、「Nested」 を、Java で書くと、
   インナークラス/inner class ということになり、外のクラスのメンバーにアクセスできます。
   ちなみに、インナークラス は、わざわざ継承を使うと、大げさ感がある時に、
   こんな風に、ちょこちょこっと書いて、済ませるために使います。
   しつこいですが、リファレンスのコード は、インナークラス ではありません!)

  Java を深く知らない方は、この事は無視して、知っている方は注意して、考えましょう。
  
  Kotlin の場合、明示的に/はっきりと innerキーワード を使わないと、
  インナークラス(inner class)ということにはなりません。
  
  ですから、この場合は、外側のOuterクラス への、参照を持っていない、
    独立したクラス
  であり、
    Outerクラス の、メンバー(プロパティ や メソッド のように)
  であるという事です。
  
  それを踏まえて、
    val nested_1 = Nested_1()
  を、考えてみましょう。
  私は、最初このコードで、エラー警告された時()、
  えっ、何でだ! と、かなり悩みましたが、
    このように書くと、
	class AnotherClass () {
		val subclassNoNested = Subclass().nested_1
			// subclassNoNested:SubclassNested
		}
  のようなコードで、protected は、継承された class でしか使えないはずなのに、
  こんなコードを使って、全然関係ないclass から、使うことが出来るようになってしまうからです。
  もし、このコードが許されるとしたら、
  このコードの21行目 のようなコードで、アクセスされるという事です。
  
  この部分は、リファレンスのコード とは、少し離れた話ですが、
  アクセス/可視性 修飾子 に関係があり、また、「落とし穴っぽい」 ですので、
  あえて言及させていただきました。
  
  ここで、また先ほどのコードに戻って考えていきましょう。
  今の話を踏まえて、
    private val nested_1_private = Nested_1()  // 19行目
  のように、privateキーワード を使って、他のclass からは、見えないようにしましょう。
  
  なにはともあれ、これで、Nested_1クラス が、継承クラスから見えることは、確認できました。
  
21行目:
  val nested_1_e1: Int = Nested_1().e1
  このコードが、OKなのは、なにはともあれ、e1(4行目)は、
  publicなので、他のclass から、見えてもよい ということで、OKです。
  
以上(21行目 は、ただの確認ですが、また 29~33行目 は、参考のためです)、
  protectedキーワード: サブクラス/Subクラス/子供クラス から、アクセス出来る
ことが、確認できました。


継承関係のないclass / Unrelated(o: Outer)クラス から、
Outerクラス の、a/b/c/d/Nested/Nested::e が、見えない/見える 理由

ここでの対象コードは、こうなります。
ここで、「軽い警告」 を、出していますが、
ここでは、 コンストラクタ/(o: Outer) は、関係ないです。
他のclass や、main()関数 などで、初期化する時に、関係してきます。
ポップアップします!
こんなコードで、検証してみましょう
15行目:
  ここでは、1行目 の Outerクラス の、メンバ(プロパティ、ネストされたクラスNested/line7)に、
  アクセスするために、Outerクラスのインスタンスouter を、作成しました。

17、19行目:
  ここで、outerを使って、Outerクラス の、プロパティa/line2、b/line3 に、
  アクセスしようとしていますが、
    a は、外のクラスから見えないし、
    b は、protected で、継承されたclass からしか見えない
  ということで、どちらにもアクセスできません。

23、25行目:
  ここでも、同様に、プロパティc/line4、d/line5 に、
  アクセスしようとしています。
    c は、internal で、アクセス制限してますが、
    同じファイル内なので、当然同じモジュールで、アクセス出来ます。
  また、
    d には、アクセス修飾子 が、付いていませんが、
    その時は/デフォルト で、public なので、アクセス出来ます。

29行目:
  ここで、
    Outer.Nested
  とは、7行目 の、Nestedクラス を、表します。
    / このページの、最初のコード の、最後の行に
    / val demo = Outer.Nested().foo()
  とあるように、ネストされたクラス は、このように、表現します。
  そして、この行では、Nestedクラス の、インスタンス を、作成しようとしていますが、
    Nestedクラス は、protected の、アクセス制限があるので、
  継承クラス/子供クラス ではない、 Unrelatedクラス/line13から からは、アクセス出来ません。

32行目:
  まず、
    ::
  とは、何者なのか?
  これに関しては、「32. 関数」 のところでも、
  扱いましたが、ここでは、違う使い方のようです。
    / 根本的に意味すること は、同じだとは思いますが.
  こんなコードで、調べてみました
  なにはともあれ、これを使って 「アクセスできるかどうか」 に、関しては、チェックできるようです。

  では、先ほどのコードに戻って、確認してみましょう。
  もちろん、Nestedクラス は、protected の、アクセス制限があるので、
  アクセスできませんね。

ここで、ダメ押しで:
2932行目 のコード に関して、
  7行目の、
    protected class Nested {
  を、コメントにして、
  新たに、8行目 で、
    class Nested {protected を、削除
  に、変更して、確認してみましょう。
  どうなると思いますか?
  つまり、protected ⇒ public に、変更されたわけですから、
  アクセスできるようになっているはずです。
  確認したコードが、これです


ここまで、ずっと、リファレンスのコード で確認しながら、この表 の、意味するところを、
確認してきました。
これで思ったのは、リファレンス を、丸暗記しても、実際にコードを、書いてみないと、
思いがけないコードのアクションに、多々出会う ことを実感しました。
コードで確認しつつ学習することの、大切さを再確認した次第であります。

このリファレンスも、もう少しで完成です。
思わぬトラブル(理解できな~い!)が、ないことを祈りつつ、あと少し頑張ります。
もし、理解できないことがあったら、宿題ということにしておきます。



まとめ

・ アクセス修飾子 の、可視性:
修飾子 クラスメンバ トップレベルの宣言
private クラス内からのみ参照可能 ファイル内からのみ参照可能
protected サブクラスから参照可能 使用できません
internal  モジュール内からのみ参照可能   モジュール内からのみ参照可能 
 public(デフォルト どこからも参照可能 どこからも参照可能

  この表を、暗記するというより、サンプルコードなどで、アクセス修飾子 に、出会う度に、
  ルールを確認して、使いながら覚える というのが、現実的な気がします。

protected な メンバ が、継承したclass で、override された場合 も、
 protected を、引き継ぎます