Java道|privateでメンバを守る方法

大事な情報は、むやみに触らせない。
private を使えば、クラスの中身を守り、安全な部品として育てられる。

前の記事では、クラスのメンバを外から自由に触れる状態にしておくと、不自然な値が入る危険があることを学びました。

クラスには、フィールドとメソッドがあります。
この2つをまとめてメンバと呼びます。

フィールドには、オブジェクトの大事な情報が入ります。
鬼滅の刃でたとえると、隊士の名前、体力、呼吸の力のようなものです。

もし、こうした情報をクラスの外から誰でも自由に書き換えられるとしたら、かなり危険です。

体力がマイナスになる
呼吸の力が不自然な値になる
隊士の名前が勝手に変えられる
どこで値が壊れたのか分からなくなる

このような問題が起きる可能性があります。

そこで使うのが private です。

private をつけたメンバは、クラスの外から直接アクセスできなくなります。
つまり、外から勝手に触られないように守れるのです。

鬼滅の刃でたとえると、隊士の内部情報に結界を張り、決められた場所からしか触れないようにするイメージです。

問題の原因は外から自由に触れてしまうこと

まず、前の記事で使った Sample1.java の形を確認します。

ファイル名:Sample1.java

class DemonSlayer
{
    String name;
    int stamina;
    double breathingEnergy;

    void show()
    {
        System.out.println("隊士の名前は" + name + "です。");
        System.out.println("体力は" + stamina + "です。");
        System.out.println("呼吸の力は" + breathingEnergy + "です。");
    }
}

class Sample1
{
    public static void main(String[] args)
    {
        DemonSlayer mizuki = new DemonSlayer();

        mizuki.name = "水月";
        mizuki.stamina = 100;
        mizuki.breathingEnergy = 20.5;

        mizuki.show();
    }
}

このプログラムでは、DemonSlayer クラスの外にある main メソッドから、フィールドに直接値を入れています。

mizuki.name = "水月";
mizuki.stamina = 100;
mizuki.breathingEnergy = 20.5;

このように、オブジェクト名、ドット、フィールド名という形で、外からフィールドを直接操作しています。

値が自然な範囲なら、一見問題はなさそうに見えます。

フィールド入れている値状態
name水月自然
stamina100自然
breathingEnergy20.5自然

しかし、外から直接触れるということは、正しい値だけでなく、おかしな値も入れられてしまうということです。

たとえば、次のような代入も書けてしまいます。

mizuki.breathingEnergy = -10.0;

呼吸の力が -10.0 になるのは、隊士の状態としてかなり不自然です。

また、次のような値も危険です。

mizuki.stamina = -50;

体力が -50 の隊士というのも、自然な状態ではありません。

鬼滅の刃でたとえると、隊士本人の状態を無視して、外部から無理やり「呼吸の力はマイナス」「体力はマイナス」と書き換えているようなものです。

これは、隊士というオブジェクトを自然に扱えているとは言えません。

private は外から直接触れないようにする指定

こうした危ない直接操作を防ぐために使うのが private です。

private は、メンバをクラスの外から直接使えないようにするための指定です。

フィールドに private をつけると、次のようになります。

ファイル名:Sample1.java(修正後)

class DemonSlayer
{
    private String name;
    private int stamina;
    private double breathingEnergy;

    void show()
    {
        System.out.println("隊士の名前は" + name + "です。");
        System.out.println("体力は" + stamina + "です。");
        System.out.println("呼吸の力は" + breathingEnergy + "です。");
    }
}

class Sample1
{
    public static void main(String[] args)
    {
        DemonSlayer mizuki = new DemonSlayer();

        // mizuki.name = "水月";
        // mizuki.stamina = 100;
        // mizuki.breathingEnergy = 20.5;

        mizuki.show();
    }
}

ここでは、name、stamina、breathingEnergy に private をつけています。

private String name;
private int stamina;
private double breathingEnergy;

これで、この3つのフィールドは private メンバになります。

private メンバは、クラスの外から直接アクセスできません。

そのため、次のような書き方はできなくなります。

mizuki.name = "水月";
mizuki.stamina = 100;
mizuki.breathingEnergy = 20.5;

この変化が、private の大きな役割です。

外から直接フィールドを書き換える道を閉じることで、危ない値が勝手に入ることを防ぎやすくなります。

private は隠して守るためのしくみ

private は、ひとことで言えば、メンバを隠して守るしくみです。

ただし、ここでいう「隠す」は、見えなくして困らせるという意味ではありません。

外から勝手に触れないようにする
クラスの中で責任を持って管理する
不自然な状態を作らせにくくする

という意味です。

鬼滅の刃でたとえると、隊士の名前や体力、呼吸の力を、誰でも触れる場所に置かないようにすることです。

隊士名簿や呼吸の状態記録は、大事な情報です。
誰でも自由に書き換えられると困ります。

だから、結界や鍵で守り、決められた内部の仕組みだけが扱えるようにします。

private の役割鬼滅の刃でたとえると
外から直接触れないようにする隊士情報に結界を張る
内部で管理する隊士本人や管理役だけが扱う
危ない値を入りにくくする不自然な状態を防ぐ
クラスを安全にする信頼できる隊士管理にする

private は、クラスの中身を守るための基本の道具です。

private をつけると何が変わるのか

private をつける前は、クラスの外からフィールドに直接アクセスできました。

mizuki.breathingEnergy = -10.0;

この書き方ができると、呼吸の力に不自然な値を入れられてしまいます。

しかし、breathingEnergy を private にすると、外から直接アクセスできなくなります。

private double breathingEnergy;

この状態では、main メソッドのようなクラスの外側から、次のような操作はできません。

mizuki.breathingEnergy = -10.0;

つまり、private によって、外からの危ない直接代入を防げます。

状態外から直接代入できるか危険性
private なしできる不自然な値が入りやすい
private ありできない外からの直接操作を防げる

ここで大切なのは、private は「値の意味を自動で判断する魔法」ではないことです。

private をつけただけで、すべての不正な値を完全に防げるわけではありません。
しかし、外から直接フィールドを壊される入口を閉じられるので、安全な設計への大きな一歩になります。

なぜ private にすると安全に近づくのか

private にすると安全に近づく理由は、外から自由に触れなくなるからです。

たとえば、breathingEnergy が外から直接触れる状態なら、次のような値をどれでも入れられます。

代入する値状態
20.5自然
0.0自然な可能性がある
-10.0不自然

外から直接触れる状態では、自然な値も不自然な値も同じように入れられてしまいます。

しかし private にすると、少なくともクラスの外からは次のような書き換えができなくなります。

mizuki.breathingEnergy = -10.0;

これは、危ない操作の入口をふさぐということです。

鬼滅の刃でたとえると、隊士の呼吸記録を誰でも書き換えられる紙にしておくのではなく、鍵のかかった記録帳にするようなものです。

鍵があれば、外部の人が勝手にマイナスの呼吸値を書き込むことはできません。

クラスの中からは private メンバを使える

ここで大事なのは、private にしたメンバが完全に使えなくなるわけではないことです。

private メンバは、同じクラスの中からなら使えます。

次の show() メソッドを見てください。

void show()
{
    System.out.println("隊士の名前は" + name + "です。");
    System.out.println("体力は" + stamina + "です。");
    System.out.println("呼吸の力は" + breathingEnergy + "です。");
}

name、stamina、breathingEnergy は private になっています。

private String name;
private int stamina;
private double breathingEnergy;

それでも、show() メソッドの中ではそのまま使えます。

なぜなら show() は DemonSlayer クラスの中にあるメソッドだからです。

場所private メンバにアクセスできるか
同じクラスの中できる
クラスの外できない

鬼滅の刃でたとえると、隊士の内部情報は外部の人には触れません。
しかし、隊士本人の内部処理や、隊士クラスの中にある正規の機能からは扱えます。

つまり private は、完全に封印するものではありません。

外から勝手に触れないようにしつつ、クラスの中では責任を持って扱えるようにする仕組みです。

図:private は外からの直接アクセスを防ぐ

↓クリックすると拡大表示されます。

この図が示していること

この図では、Sample1 の main から DemonSlayer クラスの private フィールド breathingEnergy に直接アクセスしようとしている様子を表しています。

しかし、private がついているため、外からの直接アクセスは途中で遮られています。

ここから分かるのは、private はフィールドを完全に消すものではなく、外から勝手に触れないようにする守りのしくみだということです。
特に、breathingEnergy に -10.0 のような不自然な値を直接入れる道を閉じられるところが重要です。

private は見せるものと隠すものを分ける入口

private を理解するときに大切なのは、全部を外に見せる必要はないという感覚です。

クラスを設計するときは、次の2つを分けて考えます。

分けるもの内容
外から使わせたいもの必要な操作として公開するメソッド
外から直接触らせたくないもの内部で守るフィールド

たとえば、DemonSlayer クラスでは、show() は外から使わせてもよいメソッドです。

mizuki.show();

show() は、隊士の状態を表示するための自然な操作だからです。

一方で、name、stamina、breathingEnergy は、外から直接書き換えられると危険な情報です。

そのため、private をつけて守る候補になります。

メンバ外から直接触らせたいか理由
name注意が必要名前を勝手に壊される可能性がある
stamina直接触らせたくないマイナス体力などが入りうる
breathingEnergy直接触らせたくないマイナスの呼吸の力が入りうる
show()使わせてもよい状態を表示する自然な操作

鬼滅の刃でたとえると、隊士の状態を確認することは許してもよいです。
しかし、隊士の内部記録を書き換えることは、誰にでも許してよいものではありません。

private は、この「見せるもの」と「隠すもの」を分けるための入口です。

private にしただけでは値を設定できない問題もある

ここで、ひとつ大切な点があります。

フィールドを private にすると、外から直接値を入れられなくなります。

つまり、次のような代入はできません。

mizuki.name = "水月";
mizuki.stamina = 100;
mizuki.breathingEnergy = 20.5;

これは安全性の面ではよいことです。
しかし、そのままだと外から隊士の名前や体力を設定する方法がなくなってしまいます。

この状態では、show() を呼び出しても、フィールドには初期値のままの値が入っています。

フィールド初期値のイメージ
String namenull
int stamina0
double breathingEnergy0.0

つまり private は、外からの直接操作を防ぐ役割を持ちます。
ただし、必要な値を安全に設定するには、次の段階で「決められたメソッドを通して設定する」考え方が必要になります。

ここではまず、private によって外から直接触れなくなる、という基本を押さえることが大切です。

クラスの中では private フィールドを自由に扱える

private の基本ルールをもう少し整理します。

DemonSlayer クラスの中では、private フィールドを使えます。

class DemonSlayer
{
    private String name;
    private int stamina;
    private double breathingEnergy;

    void show()
    {
        System.out.println("隊士の名前は" + name + "です。");
        System.out.println("体力は" + stamina + "です。");
        System.out.println("呼吸の力は" + breathingEnergy + "です。");
    }
}

show() の中では、name、stamina、breathingEnergy をそのまま参照しています。

これは、show() が同じ DemonSlayer クラスの中にあるからです。

外からは触れない。
中からは使える。

この違いが private の中心です。

アクセスする場所private フィールドを使えるか
DemonSlayer クラスの中show() の中使える
Sample1 クラスの中main の中使えない

鬼滅の刃でたとえると、隊士の内部記録は外部の人には見せません。
しかし、隊士本人が自分の状態を確認して報告することはできます。

show() は、その「本人からの報告」のような役割です。

図:private メンバはクラスの中から使える

↓クリックすると拡大表示されます。

この図が示していること

この図では、private フィールドが DemonSlayer クラスの内部で守られている様子を表しています。

Sample1 の main から private フィールドへ直接触ろうとする赤い矢印は、途中で遮られています。
一方で、同じ DemonSlayer クラスの中にある show() からは、private フィールドへアクセスできています。

ここから分かるのは、private は「完全に使えなくする指定」ではないということです。
クラスの外からは隠し、クラスの中では責任を持って使えるようにする指定です。

8章の自由さから9章の安全さへ

8章では、クラスを作り、オブジェクトを作り、メンバにアクセスする基本を学びました。

そこでは、まず「どう使うか」が中心でした。

たとえば、オブジェクトを作って、フィールドに値を入れ、メソッドを呼び出す流れです。

しかし、9章ではそこに「どう守るか」という視点が加わります。

学習段階視点内容
8章使うクラスを作り、メンバにアクセスする
9章守るメンバを外から勝手に触らせない

鬼滅の刃でたとえると、8章は「隊士を作り、情報や技を持たせる段階」です。
9章は「隊士の大事な情報を守り、安全に扱う段階」です。

private は、その最初の一歩です。

フィールドを守る
外からの勝手な書き換えを防ぐ
自然な状態を保ちやすくする

この3つにつながる、とても大切な指定です。

private があるとありえない状態を作りにくくなる

private の大きな価値は、外からありえない状態を作りにくくなることです。

たとえば breathingEnergy が private でなければ、外から次のように書けます。

mizuki.breathingEnergy = -10.0;

しかし private にしておけば、クラスの外から直接このような代入はできません。

これにより、少なくとも外部のコードが勝手に、

呼吸の力がマイナスの隊士
体力が不自然な隊士
内部状態が壊れた隊士

を作ってしまう危険を減らせます。

もちろん、private だけで完全な安全が完成するわけではありません。

安全に値を設定するためには、次に、正しい入口となるメソッドを用意する考え方が必要になります。
ただ、最初の段階として「外から直接触れないようにする」ことは、とても強い守りになります。

鬼滅の刃でたとえると、private は隊士の内部情報を守る結界です。
結界を張ることで、外から勝手に体力や呼吸の力を書き換えられないようにします。

private を使うとクラスの責任がはっきりする

private を使うと、クラスの責任がはっきりします。

フィールドを外から自由に触らせる場合、値を正しく保つ責任が外側のコードにも広がってしまいます。

しかし private にすると、フィールドの管理はクラス自身が担当する、という考え方になります。

設計値を管理する責任
フィールドを外から直接触れる外側のコードにも責任が広がる
フィールドを private にするクラス自身が内部状態を管理する

鬼滅の刃でたとえると、隊士の体力や呼吸の状態は、外部の誰かが勝手に書き換えるものではありません。
隊士本人、または決められた管理の仕組みが責任を持って扱うものです。

Javaでも同じです。

フィールドを private にすることで、「この情報はこのクラスが責任を持って管理する」という設計になります。

private を学ぶときの大切な見方

private を学ぶときは、次のように考えると分かりやすいです。

見るポイント意識すること
フィールド外から直接触らせてよいか
値の自然さ不自然な値が入る可能性はないか
クラスの責任内部状態を誰が管理するべきか
メソッド外から使わせる入口にするか
privateまず外からの直接操作を防ぐ

特にフィールドは、オブジェクトの状態そのものです。

隊士の名前、体力、呼吸の力は、隊士の状態を表す大切な情報です。
これらが不自然な値になると、オブジェクト全体の意味が崩れてしまいます。

だからこそ、フィールドは private で守るという考え方が重要になります。

いちばん大事な感覚

privateでメンバを守る方法で大切なのは、次の感覚です。

ポイント内容
問題の原因外からメンバを無制限に触れてしまうこと
private の役割クラスの外から直接アクセスできないようにする
クラス内の扱い同じクラスの中からは private メンバを使える
守る意味不自然な値を外から入れられにくくする
設計の考え方中身は隠し、必要な操作だけ外に見せる
次につながること正しい入口となるメソッドを用意する考え方

鬼滅の刃でたとえると、隊士の大事な内部情報は、誰でも勝手にいじれるべきではありません。

体力や呼吸の力のような重要な値は、外からむやみに触らせず、まず private で守ります。
そのうえで、必要な操作だけを安全な入口として用意していくことが、これからのクラス設計で大切になります。

private が分かると、クラスは単なる情報の入れ物ではなく、自分の中身を守りながら安全に使ってもらう部品として見えてきます。