Javaには可視性という概念があります。(ほかの言語にもありますが、使いこなせないのでちゃんと説明することはできない)
可視性を理解せずに実装すると、危険なので必ず理解しましょう。
といいつつ、この記事ではメソッド形式での紹介にとどめます。
※毎度のことながら、こう書いた方がわかりやすい、そこちょっと認識違うとかあればぜひコメントなどで教えてください。
可視性とは?
可視性とは「どこまで見えるか」「どこまで使えるか」のようなイメージです。
Vol.5まで見ている前提でいうと、可視性によって「どのクラスで使えるか」という観点になります。
可視性の種類
Javaにはクラス、メソッド、などに用いるか姿勢の種類が大きく4つあります。
- public
- protected
- package private
- private
上から順に広範囲で利用することができます。
※下記ページのAccess Levelsの表を参照
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
public
同一プロジェクト内からならどこからでも利用が可能。
publicがついたメソッドは、属するクラスのインスタンスを生成すれば、利用可能です。
例)
package jp.co.sorpy.main;
public class MainController{
public void outputLog(){
System.out.println("このメソッドはpublic")
}
}
前述のように記述すると
package jp.co.sorpy.main.controller.hogehoge;
public class SubController{
public void hoge(){
MainController mainController = new MainController();
mainController.outputLog();
}
}
のように記述すればどこからでも呼び出しは可能。
protected
または継承(extends)したクラス内で利用可能、publicより可視性が狭くなる(低くなる)。(継承はこのシリーズでは紹介していないのでいずれ。。。)
また同一package内でも呼び出し可能。
後述するpackage privateと同等の使い方が可能。
例)
package jp.co.sorpy.main;
public class MainController{
protected void outputLog(){
System.out.println("このメソッドはpublic")
}
}
前述のように記述すると
package jp.co.sorpy.main.controller;
public class SubController extends MainController{
public void hoge(){
outputLog();
}
}
このようにextends MainControllerのついたクラス内で、
MainControllerをnewしていなくても呼び出すことができます。
(正確にはextendsをつけている場合は子が呼ばれたときに親子同時にnewされる)
なおpublicもこの利用方法は可能ですが、protectedにすることで、
publicのようにどこでも使えては困るが、
継承したクラスでは使えていい場合にこのようにprotectedを利用します。
package private
同一packageであればどこからでも利用が可能。
同一packageとは、Javaのクラスに必ず記載のある1行目の「package jp.co.hoge.controller.fuga;」の記述部分である。
package privateはほかと違い、「何もつけない」(例参照)。
例)
package jp.co.sorpy.main;
public class MainController{
void outputLog(){
System.out.println("このメソッドはpublic")
}
}
前述のように記述すると
package jp.co.sorpy.main;
public class SubController{
public void hoge(){
MainController mainController = new MainController();
mainController.outputLog();
}
}
このようにpackageの部分が同じであれば呼び出すことが可能です。
private
同一クラス内でのみ利用可能である。
もっとも可視性の狭い(低い)のがこのprivate。
例)
package jp.co.sorpy.main;
public class MainController{
private void outputLog(){
System.out.println("このメソッドはpublic")
}
public void hoge(){
outputLog();
}
}
前述のとおりoutputLog()メソッドはMainControllerからしか呼べません。
前段の3種類の方法で利用しようとするとコンパイルエラーになります。
可視性を検討する際に留意すべきこと
プログラムにおいては、「できることを極力減らす」ことが読みやすく、
メンテナビリティの高いコードになると、筆者は考えています。
※機能に関してはできることが多いほうがいい場合もある。
そのため、原理原則としては、privateで実装し、
必要に応じ可視性を上げていくというのが安心、安全なコードになると考えています。
ただし、可視性をどうするかについては一言で説明できないし、
時と場合によって検討の余地もあります。
各クラスがAPIであると解釈すれば、外部とのやり取りのために必ずpublicメソッドが必要になります。
新人、若手の皆さんは実際にコードレビューで指摘を受けたり、
イケてるコードを参照することをお勧めします。
やはりこの辺りは実践して身に着けていただきたいところ。
これを知っているだけでは有効な状況を理解するのは難しい。