
Java道|継承におけるメンバアクセスのしくみ
親子の関係でも、すべてを直接見られるわけではない。
private と protected を理解すると、継承の中で守る情報と共有する情報の境界線がはっきり見えてきます。
Javaの継承では、スーパークラスの性質や機能をサブクラスが受け継げます。
しかし、ここで大切なのは、受け継いだからといって、すべてのメンバに自由に直接アクセスできるわけではない という点です。
クラスのフィールドやメソッドには、どこからアクセスできるかを決める アクセス修飾子 を付けられます。
今回の中心になるのは、private と protected です。
鬼滅の刃風にたとえると、DemonSlayer クラスは鬼殺隊士としての共通情報を持つ親クラスです。
そこから PillarSlayer クラスという柱の隊士クラスを作るとします。
柱は鬼殺隊士の一種なので、鬼殺隊士としての情報を受け継ぎます。
けれども、親クラスが内部だけで守りたい情報まで、子クラスが勝手に直接触れるわけではありません。
たとえば、隊士名簿の中には次のような情報があります。
| 情報の種類 | 鬼滅の刃風のイメージ | アクセス修飾子 |
|---|---|---|
| 親クラスだけで厳重に管理したい情報 | 隊士名簿の奥にある内部管理情報 | private |
| 子クラスにも使わせたい情報 | 柱にも共有される隊士の基本情報 | protected |
つまり、継承では「親から子へ受け継ぐ」ことと、「子から直接触れる」ことを分けて考える必要があります。
この境界線を作るのが、private と protected です。
継承したら親クラスのメンバは何でも使えるのか
まず結論からいうと、継承したからといって、スーパークラスのメンバすべてにサブクラスから直接アクセスできるわけではありません。
ここはとても大事です。
サブクラスはスーパークラスの性質を受け継ぎます。
しかし、実際にそのメンバへ直接アクセスできるかどうかは、アクセス修飾子によって決まります。
たとえば、親クラスにあるフィールドが private なら、そのフィールドは親クラスの内部だけで使える情報になります。
サブクラスであっても、その private フィールドを直接読むことはできません。
鬼滅の刃風にたとえると、PillarSlayer は DemonSlayer を受け継いだ存在です。
しかし、DemonSlayer の内部保管庫にある情報を、PillarSlayer が勝手に開けることはできません。
親子関係だから何でも見える、というわけではないのです。
private が意味すること
private は、そのクラスの内部からだけアクセスできる という指定です。
これは継承している場合でも変わりません。
スーパークラスに private フィールドがある場合、そのフィールドはサブクラスから直接使えません。
たとえば、DemonSlayer クラスに次のようなフィールドがあるとします。
| フィールド | 意味 |
|---|---|
| name | 隊士の名前 |
| rank | 階級 |
これらが private なら、DemonSlayer クラスの中では使えます。
しかし、DemonSlayer を継承した PillarSlayer クラスの中から、name や rank を直接書くことはできません。
private のアクセス範囲
| アクセスしたい場所 | private メンバに直接アクセスできるか |
|---|---|
| 同じクラスの中 | できる |
| サブクラスの中 | できない |
| 別のクラス | できない |
private は、かなり強く守られた指定です。
継承関係があっても例外ではありません。
↓クリックすると拡大表示されます。

サブクラスから private メンバに直接アクセスできない理由
継承を学び始めると、親クラスのメンバを受け継ぐなら、子クラスから直接見えてもよさそうに感じるかもしれません。
しかし、Javaでは private をかなり厳密に扱います。
private は、
そのクラス自身だけが責任を持って扱う内部情報
という意味を持つからです。
鬼滅の刃風にたとえると、DemonSlayer クラスが持っている name や rank が private の場合、それは鬼殺隊士クラスの中だけで管理される隊士名簿です。
PillarSlayer は DemonSlayer を受け継いでいます。
しかし、親クラスの内部台帳を直接開いて、name や rank を勝手に読み書きすることはできません。
これは不便に見えるかもしれませんが、クラスの安全性を守るためには大切です。
勝手に内部データを変更できてしまうと、
| 問題 | 内容 |
|---|---|
| 不正な値が入る | 階級にありえない値が入る可能性がある |
| 管理ルールが崩れる | 本来メソッド経由で行うべき処理を飛ばしてしまう |
| クラスの責任範囲が曖昧になる | 誰がその値を管理しているのか分かりにくくなる |
このような問題が起こりやすくなります。
そのため、private はカプセル化を守るためにとても重要です。
protected が登場する理由
一方で、スーパークラスとサブクラスは近い関係にあります。
親クラスが持っている情報を、子クラス側でも使いたい場面があります。
そのようなときに使えるのが protected です。
protected を付けたメンバは、サブクラスから直接アクセスできます。
鬼滅の刃風にたとえると、DemonSlayer クラスの基本情報のうち、柱である PillarSlayer にも共有してよい情報を protected にしておくイメージです。
たとえば、次のような情報を子クラスの表示メソッドで使いたいとします。
| 情報 | 子クラスで使いたい理由 |
|---|---|
| name | 柱の名前を表示したい |
| rank | 柱の階級を表示したい |
| area | 柱の担当区域と一緒に表示したい |
このような場合、name と rank を protected にしておくと、PillarSlayer の中から直接使えます。
protected は親子で共有しやすい指定
protected は、private と public の中間のような感覚で理解すると分かりやすいです。
| 修飾子 | サブクラスから直接アクセスできるか | イメージ |
|---|---|---|
| private | できない | 親クラスだけの内部情報 |
| protected | できる | 子クラスにも共有する情報 |
| public | できる | 外部にも公開する情報 |
今回の中心は、private と protected の違いです。
親クラスにあるメンバをサブクラスの中で直接使いたい場合、private ではなく protected が候補になります。
ただし、何でも protected にすればよいわけではありません。
外から守りたい情報なのか、子クラスに共有してよい情報なのかを考えて使い分けることが大切です。
protected メンバを確認する
ファイル名:Sample3.java
class DemonSlayer
{
protected String name;
protected String rank;
public DemonSlayer()
{
name = "隊士未登録";
rank = "階級未設定";
System.out.println("鬼殺隊士を作成しました。");
}
public void setSlayer(String n, String r)
{
name = n;
rank = r;
System.out.println("名前を" + name + "に、階級を" + rank + "にしました。");
}
public void show()
{
System.out.println("隊士の名前は" + name + "です。");
System.out.println("階級は" + rank + "です。");
}
}
class PillarSlayer extends DemonSlayer
{
private int area;
public PillarSlayer()
{
area = 0;
System.out.println("柱クラスの隊士を作成しました。");
}
public void setArea(int a)
{
area = a;
System.out.println("担当区域を" + area + "にしました。");
}
public void newShow()
{
System.out.println("柱の名前は" + name + "です。");
System.out.println("階級は" + rank + "です。");
System.out.println("担当区域は" + area + "です。");
}
}
class Sample3
{
public static void main(String[] args)
{
PillarSlayer slayer1;
slayer1 = new PillarSlayer();
slayer1.newShow();
}
}Sample3.java で注目するところ
このプログラムでいちばん大事なのは、DemonSlayer クラスの name と rank が protected になっているところです。
protected String name;
protected String rank;この指定により、サブクラスである PillarSlayer の newShow() メソッドから、name と rank を直接使えます。
newShow() の中では、次の3つを表示しています。
| 表示している内容 | 定義されている場所 |
|---|---|
| name | スーパークラス DemonSlayer |
| rank | スーパークラス DemonSlayer |
| area | サブクラス PillarSlayer |
つまり、newShow() は親クラスから受け継いだ protected メンバと、子クラスで追加した private メンバの両方を使っています。
public void newShow()
{
System.out.println("柱の名前は" + name + "です。");
System.out.println("階級は" + rank + "です。");
System.out.println("担当区域は" + area + "です。");
}ここで name と rank を直接使えているのは、protected だからです。
実行結果の例
鬼殺隊士を作成しました。
柱クラスの隊士を作成しました。
柱の名前は隊士未登録です。
階級は階級未設定です。
担当区域は0です。まず、PillarSlayer オブジェクトを作成すると、継承のルールにより、先に DemonSlayer のコンストラクタが動きます。
鬼殺隊士を作成しました。そのあと、PillarSlayer のコンストラクタが動きます。
柱クラスの隊士を作成しました。最後に newShow() が呼ばれ、name、rank、area が表示されます。
このとき、name と rank は親クラス DemonSlayer にあるフィールドです。
しかし protected なので、子クラス PillarSlayer の newShow() から直接参照できています。
もし name と rank が private だったらどうなるか
もし DemonSlayer クラスの name と rank が protected ではなく private だった場合、PillarSlayer の newShow() で次のような書き方はできません。
System.out.println("柱の名前は" + name + "です。");
System.out.println("階級は" + rank + "です。");なぜなら、private フィールドはスーパークラスの内部だけで使える情報だからです。
サブクラスである PillarSlayer の中からでも、name と rank を直接読むことはできません。
違いを整理すると、次のようになります。
| スーパークラスのフィールド指定 | サブクラスから直接使えるか |
|---|---|
| private String name | 使えない |
| protected String name | 使える |
この1行の違いが、継承におけるメンバアクセスではとても大きな差になります。
newShow() が意味していること
newShow() は、PillarSlayer 専用の表示メソッドです。
このメソッドでは、柱としての担当区域だけでなく、親クラスにある名前や階級も一緒に表示しています。
鬼滅の刃風に考えると、柱を紹介するときには、次の情報をまとめて見たい場面があります。
| 表示したい情報 | 内容 |
|---|---|
| 名前 | どの隊士なのか |
| 階級 | どの立場なのか |
| 担当区域 | どこを任されているのか |
このとき、親クラスの name と rank に子クラスから触れられないと、PillarSlayer 専用の表示が作りにくくなります。
そこで protected が役立ちます。
protected は、
親子関係の中で必要な情報を共有しやすくするための指定
と考えると分かりやすいです。
実行の流れを整理する
Sample3.java の流れを順番に整理すると、次のようになります。
| 順番 | 処理 | 内容 |
|---|---|---|
| 1 | PillarSlayer slayer1; | PillarSlayer 型の変数を用意する |
| 2 | slayer1 = new PillarSlayer(); | オブジェクトを作成する |
| 3 | DemonSlayer() | 親クラス側の name と rank を初期化する |
| 4 | PillarSlayer() | 子クラス側の area を初期化する |
| 5 | slayer1.newShow(); | name、rank、area を表示する |
この流れの中で特に大事なのは、newShow() です。
newShow() では、親クラスの protected メンバである name と rank に直接アクセスしています。
さらに、子クラス自身の private メンバである area にもアクセスしています。
つまり、PillarSlayer の中では、
| メンバ | 直接アクセスできる理由 |
|---|---|
| name | 親クラスで protected だから |
| rank | 親クラスで protected だから |
| area | 自分のクラスの private メンバだから |
という関係になっています。
図:private と protected の違い
↓クリックすると拡大表示されます。

この図が示していること
この図では、DemonSlayer クラスにある private メンバと protected メンバが、PillarSlayer クラスからどう見えるかを表しています。
private メンバから PillarSlayer への矢印にはバツが付いています。
これは、サブクラスであっても private メンバには直接アクセスできないことを示しています。
一方、protected メンバから PillarSlayer へは青い矢印が届いています。
これは、protected メンバならサブクラスから直接使えることを示しています。
この図から分かることは、継承しているかどうかだけでアクセスが決まるわけではない、という点です。
アクセスできるかどうかは、メンバに付いているアクセス修飾子によって決まります。
カプセル化と protected のバランス
private は、情報を強く守るための指定です。
そのクラスの内部だけでデータを管理したい場合に向いています。
一方、protected は、サブクラスにも利用させたい情報がある場合に使えます。
親クラスと子クラスの連携をしやすくする指定です。
ただし、protected は便利だからといって、何でも付ければよいわけではありません。
| 指定 | 向いている場面 |
|---|---|
| private | そのクラスの中だけで厳密に管理したい |
| protected | サブクラスにも利用させたい |
| public | 外部から広く使わせたい |
鬼滅の刃風にたとえると、DemonSlayer の内部で厳重に管理したい情報は private にします。
一方で、PillarSlayer にも使わせたい基本情報は protected にします。
つまり、設計するときには、次の視点が大切です。
| 視点 | 考えること |
|---|---|
| 守るべき情報か | 外から直接触れないようにする |
| 子クラスで使う必要があるか | protected を検討する |
| 外部に公開してよいか | public を検討する |
アクセス修飾子は、ただの文法ではありません。
クラスの責任範囲を決める設計の道具です。
private と protected をどう使い分けるか
private と protected の使い分けは、次のように考えると分かりやすいです。
| 使い分けの基準 | 向いている指定 |
|---|---|
| そのクラスだけで管理したい | private |
| サブクラスでも直接使いたい | protected |
| どこからでも使わせたい | public |
今回の Sample3.java では、name と rank を PillarSlayer の newShow() で直接表示したかったため、protected にしています。
もし、親クラスだけで値を管理し、子クラスからは専用メソッド経由で使わせたいなら、private のままにする方法もあります。
たとえば、次のような考え方です。
| 設計方針 | 例 |
|---|---|
| 子クラスから直接使わせる | protected String name |
| 子クラスから直接使わせない | private String name と getName() のようなメソッド |
どちらが正しいというより、何をどこまで見せたいかによって選びます。
protected は同じパッケージからもアクセスできる
protected には、もうひとつ覚えておきたい特徴があります。
protected はサブクラスからアクセスできるだけでなく、同じパッケージにあるクラスからもアクセスできます。
ただし、今回の中心は継承におけるアクセスです。
まずは、次の理解をしっかり押さえておけば大丈夫です。
| 修飾子 | 継承で重要なポイント |
|---|---|
| private | サブクラスから直接アクセスできない |
| protected | サブクラスから直接アクセスできる |
同じパッケージからのアクセスについては、パッケージを学ぶときにあらためて整理すると理解しやすいです。
図:DemonSlayer と PillarSlayer のメンバアクセス
↓クリックすると拡大表示されます。

この図が示していること
この図では、PillarSlayer の newShow() がどのメンバを使っているかを表しています。
DemonSlayer の name と rank から newShow() に矢印が伸びています。
これは、name と rank が protected なので、サブクラスから直接使えることを示しています。
また、PillarSlayer の area から newShow() にも矢印が伸びています。
area は PillarSlayer 自身の private メンバなので、同じ PillarSlayer クラスの中にある newShow() からは直接使えます。
つまり、newShow() は、
| メンバ | どこにあるか | なぜ使えるか |
|---|---|---|
| name | DemonSlayer | protected だから |
| rank | DemonSlayer | protected だから |
| area | PillarSlayer | 同じクラスの private メンバだから |
という関係で情報を表示しています。
鬼滅の刃風に private と protected を整理する
DemonSlayer は、鬼殺隊士という共通の土台です。
そこには、名前や階級のような基本情報があります。
PillarSlayer は、その土台を受け継いだ柱の隊士です。
柱として担当区域を持ち、さらに自分専用の表示メソッド newShow() も持っています。
このとき、親クラスの情報をどこまで子クラスに見せるかを決めるのがアクセス修飾子です。
| アクセス修飾子 | 鬼滅の刃風のイメージ |
|---|---|
| private | 鬼殺隊士クラスの内部だけで管理する秘密情報 |
| protected | 柱クラスにも共有してよい基本情報 |
| public | 外部からも使える公開された機能 |
継承しているから全部見えるのではありません。
見せる範囲をアクセス修飾子で調整することが大切です。
継承とカプセル化は一緒に考える
継承は、親クラスの機能を子クラスに受け継がせる仕組みです。
一方、カプセル化は、クラスの内部情報を守る考え方です。
一見すると、継承は情報を広げる仕組みで、カプセル化は情報を隠す仕組みに見えるかもしれません。
でも、実際にはこの2つは一緒に使うことで設計が整います。
| 考え方 | 役割 |
|---|---|
| 継承 | 共通部分を子クラスに受け継がせる |
| カプセル化 | 内部情報を勝手に触られないように守る |
| protected | 親子間で必要な情報を共有する |
| private | 親クラス内部だけで情報を守る |
鬼滅の刃風にたとえると、鬼殺隊の共通ルールは子クラスにも受け継がせます。
しかし、隊士名簿の中でも厳重に守るべき情報は private にして、子クラスにも直接触らせません。
一方で、柱クラスでも使う必要がある情報は protected にして、親子で連携しやすくします。
このように、継承とカプセル化は対立するものではありません。
守る情報と共有する情報を分けることで、より分かりやすく安全なクラス設計になります。
この内容で押さえておきたいポイント
| ポイント | 内容 |
|---|---|
| 継承してもすべてに直接アクセスできるわけではない | アクセス修飾子によって見える範囲が変わる |
| private | 同じクラスの中からだけ直接アクセスできる |
| protected | サブクラスから直接アクセスできる |
| サブクラス内の private | そのサブクラス内では直接使える |
| protected の使いどころ | 親クラスの情報を子クラスでも使いたいとき |
| private の使いどころ | 親クラス内部だけで厳密に守りたいとき |
| 設計の考え方 | 何を守り、何を子クラスに共有するかを決める |
private と protected を理解すると、継承の中での情報の見え方がはっきりします。
親クラスから受け継ぐけれど、何でも直接触れるわけではない。
この感覚を持つと、Javaのクラス設計がより安全で整理されたものになります。
