Java入門|メンバを守るアクセス制御のしくみ

戦士の情報は何でも自由に触ってよいわけじゃない。メンバを守るしくみを知ると、クラスはもっと安全になる

8章では、クラスの基本として、設計図を作り、その設計図からオブジェクトを生み出し、フィールドやメソッドを使って情報や処理を扱う流れを学びました。ここまでで、Javaのオブジェクト指向の入口はかなり見えてきたはずです。ですが、クラスの本当の強みは、ただ情報と処理をまとめられることだけではありません。不自然な使われ方や危ない操作を防ぎながら、安全に使える部品にできることにも大きな価値があります。

ドラゴンボールで考えるとわかりやすいです。たとえば、戦士の戦闘力や変身状態のような大事な情報が、クラスの外から誰でも自由に書き換えられるとしたらどうでしょうか。すると、本来ありえない値が入ったり、戦士として不自然な状態が作られたりしてしまいます。これはプログラムの世界でも同じです。クラスを「モノ」として自然に扱うためには、そのモノの中身を勝手にいじられないようにする工夫が必要です。ここでは、その入口として、メンバを守るアクセス制御の考え方をドラゴンボールのたとえでやさしく整理していきます。

クラスのメンバは便利だけれど、自由すぎると危ない

クラスの中には、フィールドとメソッドがあります。
これらをまとめてメンバと呼びましたね。

たとえば、サイヤ人クラスを考えると、こんなメンバがありそうです。

種類
フィールドname、power、energy
メソッドshow()

8章では、クラスの外からオブジェクトを通してフィールドに値を入れたり、メソッドを呼び出したりできることを学びました。これはとても便利です。ですが、何でも自由に触れる状態のままだと、便利さの反面、危うさも出てきます。

たとえば戦士の energy に対して、本来ありえない値を入れてしまうこともできてしまいます。
この「できてしまう」が問題の出発点です。

外から自由に触れると、どんな問題が起こるのか

まずは、8章で学んだのと同じような流れを、ドラゴンボールの世界に置きかえて見てみましょう。

ファイル名:Sample1.java

class Saiyan
{
    String name;
    int power;
    double energy;

    void show()
    {
        System.out.println("戦士の名前は" + name + "です。");
        System.out.println("戦闘力は" + power + "です。");
        System.out.println("気の量は" + energy + "です。");
    }
}

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

        goku.name = "悟空";
        goku.power = 9000;
        goku.energy = 20.5;

        goku.show();
    }
}

このプログラムでは、Saiyan クラスの外にある main メソッドの中から、

  • goku.name
  • goku.power
  • goku.energy

に直接値を入れています。

そのあとで show() を呼び出しているので、戦士の状態が表示されます。
ここまでは、とても自然に見えます。

一見正しく見える書き方でも、危ない入口になる

さきほどのコードは、きちんとした値を入れているので問題がないように見えます。
でも、もし外からこんなふうに書けてしまったらどうでしょうか。

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

        goku.name = "悟空";
        goku.power = 9000;
        goku.energy = -10.0;

        goku.show();
    }
}

このコードでは、気の量を -10.0 にしています。
これはプログラム上は代入できてしまうかもしれませんが、戦士の状態としてはかなり不自然です。

ドラゴンボールの感覚でいえば、

  • 気の量がマイナスになる
  • 戦闘力がありえない状態になる
  • 戦士の情報が外から無造作に壊される

というようなことが起きてしまうわけです。

ここが、アクセス制御を考える理由です。

クラスは「モノ」を自然に扱うための設計図だった

クラスは、ただ変数をまとめるための箱ではありません。
もともとは「モノ」を自然に表現するための設計図として学んできました。

ドラゴンボールで言えば、サイヤ人というクラスは「戦士として自然な状態や動き」をまとめたものです。
だから、その設計図から作られたオブジェクトに対しても、自然な扱いがされるべきです。

ところが、外から好き勝手にフィールドを書き換えられると、その自然さが壊れてしまいます。

たとえば本来なら、

  • 気の量は 0 以上であるべき
  • 戦闘力は不自然な値にならないようにしたい
  • 名前も勝手に変な状態にしたくない

というルールを守りたいはずです。

つまりクラスは、
モノらしい状態を保ちながら使えるように設計する
ことが大事なのです。

なぜ不自然な操作を防ぐ必要があるのか

「少しくらい変な値が入ってもいいのでは」と感じるかもしれません。
でも、プログラムが大きくなればなるほど、こうした不自然な操作は大きな不具合の原因になります。

たとえば、気の量がマイナスの戦士がそのまま別の処理に渡されると、

  • 表示がおかしくなる
  • 計算結果がおかしくなる
  • 条件分岐の判断がおかしくなる
  • どこで問題が起きたのか見つけにくくなる

といった困りごとにつながります。

小さなプログラムでは目立たなくても、クラスをたくさん使う複雑なプログラムになると、こうした「勝手に触れる状態」はかなり危険です。
だからJavaでは、クラスの中身を守るためのしくみが大切になってきます。

アクセス制御は「勝手に触らせない」ための考え方

ここで登場するのが、メンバへのアクセスを制限するという考え方です。
これは、クラスの外からフィールドやメソッドを自由に触れないようにして、必要な触り方だけを許すための工夫です。

ドラゴンボールでたとえるなら、戦士の大事な情報を誰でも直接いじれる状態にするのではなく、

  • 名前や戦闘力の確認は決められた方法で行う
  • 気の量を変更するなら、ちゃんとした手順を通す
  • 危ない書き換えはできないようにする

というルールを作る感じです。

つまりアクセス制御は、ただ厳しくするためのものではありません。
クラスを安全で信頼できる部品にするための守りのしくみなのです。

外から直接触る設計と、守りながら使う設計の違い

ここで、考え方の違いを表で整理してみましょう。

設計のしかた特徴
外から直接フィールドを自由に触れる手軽だが、不自然な値が入りやすい
必要な方法だけを通して扱う少し手順は増えるが、安全で自然な状態を保ちやすい

ドラゴンボールで言えば、

  • 誰でも勝手にスカウターを書き換えられる状態
  • 界王様や本人の技を通してだけ状態を変えられる状態

の違いのようなものです。

前者は自由すぎて危なく、後者は少し手間があるぶん安全です。
Javaのクラス設計では、後者の考え方がとても大事になります。

「使いやすさ」と「安全さ」を両立するための入口

アクセス制御というと、「外から触れなくするだけ」と思われがちですが、本当はそれだけではありません。
ポイントは、必要なことはできるようにしながら、危ないことはできないようにすることです。

たとえば、

  • 情報を表示する show() は使わせたい
  • 正しい値を設定するためのメソッドは使わせたい
  • でも energy に直接 -10.0 を入れるようなことは防ぎたい

という考え方です。

このように、全部を閉じるのではなく、使い道を整理して安全に公開する。
それが、クラスの機能を強くしていく第一歩です。

8章の基本があるからこそ見えてくる考え方

9章の内容は、8章で学んだ基本があってこそ理解しやすくなります。

8章では、

  • クラスは設計図
  • オブジェクトは実体
  • フィールドは情報
  • メソッドは機能
  • メンバアクセスで使う

という流れを学びました。

そのうえで9章では、
「そのメンバに、誰がどこまで触れてよいのか」
を考える段階に入っていきます。

つまり、8章が「作って使う」なら、9章は「安全に使う」へ進んでいくイメージです。
ここでアクセス制御の考え方が加わることで、クラスはもっと実践的で信頼できる部品になっていきます。

この図では、左側にある Sample1 クラスから、Saiyan クラスの energy に直接値を入れようとしている様子が描かれています。
ここで -10.0 のような不自然な値が入ってしまうことで、外から自由に触れる危うさが見えるようになっています。

中央の Saiyan クラスには、戦士の情報がまとまっています。
でもその情報を誰でも直接いじれるままだと、戦士として不自然な状態が作られてしまう可能性があります。

右側には、守られた設計として、決められた方法だけを通して扱うイメージが置かれています。
この図を見ると、アクセス制御は「意地悪に隠す」ためではなく、「自然で安全な状態を守る」ためのしくみだと理解しやすくなります。

9章の入口としていちばん大切な感覚

ここでいちばん大切なのは、次の感覚です。

  • クラスのメンバは便利だが、外から自由に触れると危ないことがある
  • クラスはモノを自然に表す設計図なので、不自然な操作は防ぎたい
  • フィールドやメソッドには、誰でも何でも触れてよいわけではない
  • 必要な操作だけを許し、危ない操作は防ぐ考え方がアクセス制御
  • これによって、誤りが起きにくいプログラムに近づいていく

ドラゴンボールで言いかえるなら、

  • 戦士の大事な情報を誰でも勝手にいじれると危ない
  • 戦士らしい自然な状態を守るために、触り方にルールが必要
  • そのルールを作るのが、メンバを守るアクセス制御の考え方

ということです。

この感覚をつかめると、9章でこれから学ぶクラスの機能が、ただの新しい文法ではなく、クラスを安全で強い部品に育てるための工夫として見えてきます。