Javaによるプログラミング入門6
クラスの理由

 Javaではいずれにしてもクラスというものを書かなければなりません。mainを持つクラスです。しかし、それ以外にクラスを書く必要はあるのでしょうか?答は、「はい」です。それはなぜでしょうか?
 その問いに簡単に答えることはできません。クラスはJavaの中心となるものであり、その意義がわかるのは、Javaがもう少しよくわかってから...だと思うのです。
 とは言え、とっかかりもなければ、考えも進まないでしょう。ここでは、クラスの意義の入り口を説明できればと思います。


 前回は、Inuというクラスを書きました。

class Inu
{
    private String name;
    Inu(String s){
        name = s;
    }
    void naku(){
        System.out.println("わん。僕は" + name + "だ。");
    }
}

 これは「犬の設計図」であるわけですが、そのオブジェクトには、ただ「名前」が格納され、必要に応じて「わん。僕は...」と表示する機能があるだけです。これだけのことをしたいなら、わざわざクラスInuを書く必要はないかもしれません。実際、人によっては、InuSample.javaを見て、「クラスInuがなぜあるのかわからない」と思うかもしれません。
 つまり、「Javaプログラムの中心部分はmainであり、mainは何かのクラスの中に書くことになっている。これはルールだからしかたがない」とクラスを1つだけ書いて、あとは、すべての処理をそのmainの中に書くことも可能なわけです。実際、ユーザの入力文字列を受け取り、それを「わん。僕は...」と一緒に表示するだけなら、その方が簡単なはずです。(入門2のHello2.javaとほぼ同じになるはずですね。)
 しかし、「名前というデータ」と「鳴くという機能」をInuというクラスにまとめたことがポイントであって、InuSample.javaというプログラムそのものは、Inuを使うサンプルの1つにすぎないのです。
 Inuは簡単なクラスですが、このようなものは、プログラムの部品と考えることができるのです。さらに言うと、一度書いてしまえば、「犬」の登場するプログラムでならどこでも使える、つまり「使いまわしのきく部品」であるわけです。

 最近のプログラムは、たいてい巨大で高機能です。そのようなプログラムを書くのはさぞ大変だろうと思います。絶対大変なはずです。^^)そのようなプログラムを書く場合に、単純で有効な方法は、まずプログラムの部品を作って、それを組み上げるという方法です。(もちろん、全体の設計が最初にあってですが。)
 それは、クラスのない言語でも同じです。しかし、クラスは、そのような部品として、とても使いやすいものなのです。それは、「データ」だけではなく、「データ」(たとえば、名前)と「機能」(たとえば、鳴くということ)をあわせた「もの」を表わすことができるからです。

 たとえば、動物園をシミュレートするプログラムを書きたいとします。いろいろな動物がいるとすると、プログラムはかなり複雑になりそうです。そんなとき、Lion(ライオン)とかKuma(熊)というクラスを作り、それらに「吼えるメソッド」hoeruや「昼寝するメソッド」neruを持たせ、

  Lion.hoeru();   //ライオンに吼えさせる
  Kuma.hirune();   //熊に昼寝をさせる

などとすれば、わかりやすいプログラムになるのではないでしょうか。また、クラスLionを考えるときは、ライオンのことだけ考えればよいので、間違いも少なくなると思います。
 つまり、クラスをうまく使えば、「わかりやすい」、「(書くときに)考えやすい」、「(失敗したときに)直しやすい」プログラムになるのです。
 要するに、とっかかりとしては、「クラスはプログラムを構築するための部品になる」と考えるとよいと思います。


  ところで、クラスInuでは、nameをprivate、つまり非公開にしました。これはなぜでしょうか。これは少し難しい話になります。
 「privateを付けると、他のクラスからnameを直接操作することができなくなる」と書きました。逆に、もし、このprivateがなければ、たとえば、クラスInuSampleのmainの中などで、

Inu d = new Inu("太郎");
d.name = "次郎";

のようなコードが書けるようになります。ここで、d.nameは、「dの指し示す(参照する)オブジェクトのname」を意味します。
 つまり、簡単にInuオブジェクトのnameを変更できてしまうのです。しかし、privateにしておくとこのようなコードは書けなくなります。書くとコンパイルエラーになるからです。下の例を見てください。

//InuSample3.java
//このプログラムはコンパイル時にエラーになります
class Inu
{
    private String name;
    Inu(String s){
        name = s;
    }
    void naku(){
        System.out.println("わん。僕は" + name + "だ。");
    }
}

class InuSample3
{
    public static void main(String[] args){
        Inu d = new Inu("太郎");    //これは問題ない
        d.name = "次郎";            //これはエラー
        d.naku();                   //これは問題ない
    }
}

Fig.1 コンパイルエラー(privateなフィールドにアクセスできない)

 「d.name = "次郎";」は、privateなデータを直接書き換えようとしているので、コンパイラが「それはできない」と言ってエラーにするのです。
 しかし、ここで、Inuの「private String name;」のprivateだけ削除してコンパイルするとエラーはなくなり、次のように実行できます。

Fig.2 privateを取った場合

 「はて、privateがある方が不便じゃないか」と思ったかもしれません。もちろん、場合によっては、privateがない方がよいかもしれません。しかし、一般的には、「データを自由に、直接変更できる」ということはいいことではないのです。
 今はまだ短いプログラムしか書いていませんが、長いプログラムを想像してみてください。長いプログラムでは、データを間違って変更してしまうということが起こるのです。(そうなんです。)もちろん、プログラマのミスで、です。
 しかし、private宣言をしておけば、「直接的な変更」(つまり「誤った変更」である可能性があるもの)はコンパイルエラーになるはずなのです。初心者は、コンパイル時にエラーが出るとがっかりするようですが、本当は、コンパイル時にエラーが出るのは「ラッキーッ」なのです。すぐに間違いがわかり、直せるからです。もし、「犬の名前を変えるつもりはなかったのに間違って変えてしまい、しかもコンパイルエラーにならなかった」としたら、どうでしょう。これは、プログラムの実行時に予想もしないエラーになるかもしれないのです。
 今は、たかが犬の名前なので、「予想もしない実行時エラー」はおおげさかもしれません。(でも、あるかもしれませんよ。)もちろん、もっと重要なデータもあるでしょう。なんにしても、一般に、データは保護する必要があるのです。そして、そのためには、privateを活用するとよいのです。もちろん、「本当にデータを変更したいときは変更できる仕組み」をつけることもできます。その場合でも、「その仕組みを通してのみ変更できる」となるので、ミスを防ぎやすいわけです。これはあとで紹介しましょう。
 初心者にはピンと来ないかと思いますが、そんなもんかなあ、と思っておいてください。

 同じことですが、これを「クラスはプログラムの部品」という考え方から見ることもできます。部品内部のデータ(フィールドというのでしたね)を部品の外から簡単に変更できるようでは、部品として安全とは言えないのではないでしょうか。

 以上の理由から、この講義では、特別な理由がない限り、フィールドはprivateにします。

 一方、メソッドはどうでしょうか。たとえば、部品の内部動作に相当するようなメソッドはprivateにします。privateを付けることでメソッドもprivateにできるのです。しかし、Inuのnakuは、クラスの外でもじゃんじゃん使いたいメソッドです。(「犬が鳴く」は内部動作ではないですよね。)そのため、nakuにはprivateを付けませんでした。むしろ、「どこでも使える」という意味のpublicを付けてもよいと思います。ただ、これには少し説明が必要です。
 実は、Javaのクラスはパッケージとよばれるグループに分類することができます。そしてクラスを定義するところでパッケージ(=グループ)を指定しないと、「無名のパッケージ」というものに入ることになります。InuもInuSampleもパッケージを指定していないので、同じ「無名パッケージ」内にあるということになるわけです。
 publicなものは「どこでも使える」と書きましたが、それは、「違うパッケージからでもアクセスできる」という意味なのです。nakuなどは、1つのパッケージ内で使うように限定する理由はないので、publicを付けてもよいわけです。ただ、この講座では、「無名のパッケージ」以外のパッケージを、(パッケージの説明の章以外では)使うことはありません。そこで、わざわざpublicを付けていないのです。publicもprivateも付けなければ、「同じパッケージ内では自由に使える」という意味になるからです。
 このように、データを保護したり、メソッドを公開することなどをアクセス制御といいます。これは、大きなプログラムを書くときに必要になる知識です。これはパッケージの説明が済んでから、もう一度考えることにしましょう。


目次のページ

前のページ  後のページ