アクセス修飾子:publicとprivateで情報を守ろう

docs

引続き、クラスについて説明します。

クラスとオブジェクトの概念 – オブジェクト指向の入り口 | ToolDocs

クラスは設計図、オブジェクトはそれから作られる実体だったよね。今回は、そのクラスの中に書く「情報」を、どうやって守っていくか、という大事な話をしよう。

情報って何? なぜ守るの?

ここでいう「情報」って、具体的にはクラスの中にある**フィールド(変数)メソッド(関数)**のことだ。

例えば、ゲームのキャラクターを作るクラスを想像してみて。 キャラクターには「HP(体力)」や「攻撃力」といったフィールドがあるよね。そして、「攻撃する」「回復する」といったメソッドがある。

もし、この「HP」という情報が、誰でも好き勝手に変更できる状態だったらどうなると思う?

  • 「あれ、さっきまでHP100だったのに、誰かが勝手にHP1にしてる!」
  • 「不正な値(例えばHP-100とか)が入っちゃった!」

こんなことになったら、ゲームは成り立たないよね。 プログラムの世界でも同じで、クラスの内部にある重要な情報が、外部から好き勝手に操作されるのを防ぐのが、今回のテーマである「情報の隠蔽(いんぺい)」、または「カプセル化」と呼ばれる考え方なんだ。

情報を隠蔽することで、こんなメリットがあるよ。

  • 安全性の確保: 外部から不正な変更をされるリスクを減らせる。
  • 保守性の向上: クラス内部の変更が、外部に影響を与えにくくなる。
  • 使いやすさの向上: 外部に公開する操作を限定することで、使い方がシンプルになる。

じゃあ、どうやって情報を隠すのか? それがアクセス修飾子の役目なんだ。

アクセス修飾子って何?

アクセス修飾子っていうのは、クラスのフィールドやメソッドが「どこからアクセスできるか」を制限するキーワードのことだよ。今回は、その中でも特に基本的な2つ、publicprivateに絞って見ていこう。

public(公開!)

publicは、その名の通り「公開」を意味するよ。publicをつけたフィールドやメソッドは、どこからでも自由にアクセスできるようになるんだ。クラスの外からでも、他のクラスからでも、何の制限もなく使える。

例を見てみよう。

Java

class Item {
    public String name; // publicなのでどこからでもアクセス可能
    public int price;   // publicなのでどこからでもアクセス可能

    public void displayItemInfo() { // publicなのでどこからでも呼び出し可能
        System.out.println("アイテム名: " + name);
        System.out.println("価格: " + price + "G");
    }
}

public class GameShop {
    public static void main(String[] args) {
        Item sword = new Item();
        sword.name = "鉄の剣"; // publicなので直接代入できる
        sword.price = 1000;    // publicなので直接代入できる

        sword.displayItemInfo(); // publicなので直接呼び出せる

        // ちなみに、こんなこともできちゃう
        sword.price = -500; // publicだとこんな不正な値も入れられちゃう!
        System.out.println("不正な価格: " + sword.price);
    }
}

この例だと、Itemクラスのnamepricepublicなので、GameShopクラスから直接値を入れたり、表示したりできるね。でも、price-500なんていう変な値も入れられちゃうのがわかるかな? これだと困るよね。

paizaで実行した結果

private(秘密だよ!)

そこで登場するのがprivateだ。privateは「私的」とか「秘密」って意味。privateをつけたフィールドやメソッドは、そのクラスの中からしかアクセスできないようになるんだ。クラスの外、つまり他のクラスからは一切触れなくなる。これが「情報の隠蔽」の基本だよ。

さっきのItemクラスのpriceprivateにしてみよう。

Java

class Item {
    public String name;
    private int price; // privateなので、このクラスの中からしかアクセスできない!

    public void displayItemInfo() {
        System.out.println("アイテム名: " + name);
        System.out.println("価格: " + price + "G");
    }

    // priceの値を設定するためのメソッド(setter)
    public void setPrice(int newPrice) {
        if (newPrice >= 0) { // ここでバリデーション(値のチェック)ができる!
            this.price = newPrice;
        } else {
            System.out.println("価格は0以上を設定してください。");
        }
    }

    // priceの値を読み出すためのメソッド(getter)
    public int getPrice() {
        return this.price;
    }
}

public class GameShop {
    public static void main(String[] args) {
        Item sword = new Item();
        sword.name = "鉄の剣";

        // sword.price = 1000; // エラーになる! privateなので直接アクセスできない

        // 代わりにsetterメソッドを使って設定する
        sword.setPrice(1000); // OK! メソッド経由なら設定できる
        sword.displayItemInfo();

        sword.setPrice(-500); // NG! setterの中でチェックされるので、不正な値は入らない
        System.out.println("現在の価格: " + sword.getPrice()); // getterで値を取得
    }
}

どうかな? Itemクラスのpriceprivateにしたら、GameShopクラスからは直接sword.price = 1000;と書けなくなったよね。これはエラーになるはずだ。

じゃあ、どうやってpriceに値を設定したり、取得したりするの? それが、setPrice()getPrice()というメソッドだ。これらは通称「setter(セッター)」と「getter(ゲッター)」と呼ばれるよ。

  • setPrice(int newPrice): priceに値を設定するためのメソッド。ここでif (newPrice >= 0)というチェックを入れることで、不正な値がpriceに入り込むのを防げるんだ!
  • getPrice(): priceの値を読み出すためのメソッド。

このように、フィールドをprivateにして直接触れないようにし、その代わりにpublicなsetter/getterメソッドを用意して、メソッド経由でしかフィールドにアクセスできないようにする。これが「情報の隠蔽(カプセル化)」の典型的なパターンなんだ。

paizaで実行した結果

なぜprivateにするの?

「結局、publicなメソッドを通せば値は設定できるんだから、直接publicでもいいんじゃない?」って思うかもしれないね。でも、大きな違いがあるんだ。

直接publicにすると、プログラムのどこからでも、どんな値でも入れられちゃう。でも、privateにしてsetterメソッドを通すことで、以下のような**「門番」**を置くことができるんだ。

  • 値の妥当性チェック: 「価格は0以上じゃないとダメ!」とか「名前は空文字列じゃダメ!」といったルールを強制できる。
  • 内部の変更が外部に影響しにくい: 例えば、将来的にpriceの型をlongに変えたくなっても、setter/getterのメソッド名は変えずに内部だけを修正すれば、外部のコードはほとんど影響を受けずに済む(メソッドの引数や戻り値の型が変わる場合は影響が出ることもあるけど、直接フィールドにアクセスするよりは断然マシ!)。
  • 複雑な処理を隠蔽: 値を設定する際に、実は裏で別の計算もしている、なんていう複雑な処理も、setterメソッドの中に隠しておくことができる。外部のコードは「このメソッドを呼べばいい」とだけ知っていればいいので、使い方がシンプルになるんだ。

まとめ

  • アクセス修飾子は、クラスのメンバー(フィールドやメソッド)がどこからアクセスできるかを制御するキーワード。
  • **public**どこからでもアクセス可能
  • **private**そのクラスの中からしかアクセスできない
  • 重要な情報を不正な操作から守るために、フィールドは基本的にprivateにするのが一般的。
  • privateなフィールドにアクセスするためには、**public**な**setter(値を設定)getter(値を取得)**メソッドを使う。
  • setterメソッドの中で値のチェックなどを行うことで、不正な値が入り込むのを防ぎ、プログラムの安全性を高められる(これをカプセル化と呼ぶ)。

今回はpublicprivateの2つだけを紹介したけど、他にもいくつかアクセス修飾子があるよ。ただ、まずはこの2つをしっかり理解して、適切に使いこなせるようになるのが大切だ。

コメント

タイトルとURLをコピーしました