【Java】クラスとインスタンスについて
クラスを宣言する
Javaのプログラムは全てクラスからできています。クラスを宣言することなくプログラムを組むことはできません。"こんにちは、Java"という文字列をコンソール表示させた場合にも、Helloというクラスにプログラムを記述しています。classはJavaの予約語でクラス宣言の始まりを示します。また慣習としてクラスの名前は大文字で始めます。
public class Hello { public static void main(String[] args) { System.out.println("こんにちはJava"); } }
{中括弧}で囲まれた範囲に、そのクラスが持つ「フィール」や「メソッド」を宣言します。フィールドは「情報を保存する場所」でいわば変数のようなものです。メソッドは「情報を処理する方法」でいわば関数のようなものです。フィールドとメソッドが、このクラスの性質を定めます。
public class クラス名{ フィールドの宣言 メソッドの宣言 }
フィールドとメソッド
フィールド:
「幅」と「高さ」という2つの情報をもつ「長方形」を表すクラスを例に考えます。フィールドは情報を保存する場所でいわば変数のようなものです。幅(width)は横の辺の長さ、高さ(height)は縦の辺の長さです。幅と高さはint型の整数であるとします。この2つの情報(フィールド)をもつ長方形のクラスRectangleを宣言します。
public class Rectangle{ private int width; private int height; }
メソッド:
メソッドは情報を処理する場所でいわば関数のようなものです。先程宣言した長方形を表すRectangleクラスに2つのメソッドを追加してみます。
幅と高さを設定するメソッドの名前をsetSize、面積を計算するメソッドの名前をgetAreaとします。
public class Rectangle{ //フィールドの宣言 private int width; private int height; //メソッドの宣言 //setSizeのメソッド public void setSize(int w,int h){ width = w; height = h; } //getAreaのメソッド public int getArea(){ return width * height; } }
setSizeのメソッド
voidはJavaの予約語で、このメソッドは情報処理の結果を戻り値として返さないということを表しています。voidは「空」や「無効」という意味です。
void メソッド名(){
ステートメント;
}
(int w,int h)の部分は、このメソッドの仮引数列です。{中括弧}でメソッドにある仮引数列をフィールド(width,height)の変数へ代入しています。
getAreaのメソッド
getArea()は長方形の面積を求めるメソッドです。setSizeと違い()内に仮引数列がないのは、width * heightの掛け算が面積を表しているからです。面積を計算するのに仮引数列の情報は必要ないということを表しています。
returnは、戻り値を指定し、メソッドの実行を中断・終了するJavaの予約語です。この場合フィールドで宣言したwidth * heightの掛け算の結果をgetAreaの戻り値として指定しています。
長方形を定義するRectangleクラスの完成
それでは、これまで長方形を定義してきたフィールやメソッドをRectangleというクラスにまとめてみます。
//長方形を定義するクラス(子) public class Rectangle{ //フィールドの宣言 //長方形の幅と高さを定義 private int width; private int height; //メソッドの宣言 //1:大きさを定義するメソッド public void setSize(int w,int h){ width = w; height = h; //以下のように記述することができる(this.がなくてもコンパイラで補完される) //this.width = w; //this.height = h; } //2:面積を求めるメソッド public int getArea(){ return width * height; } }
メインメソッドにインスタンスをつくる
それではクラスRectangleに定義したフィールドとメソッドをメインメソッド(public static void main(String[] args))から呼び出してみましょう。
メインメソッドには特別な役割があります。Javaプログラムを実行したときに最初に呼ばれるステートメントは、mainメソッドに記述する必要があるからです。Javaプログラムのコードは上から順に実行されるというわけではなく、mainメソッドの中に記述したステートメントが上から順に実行されます。
まずは、フィールドやメソッドを呼び出すためにインスタンスを作っておかなければなりません。Rectangleクラスのインスタンスを作るには、new演算子をつかいます。作ったインスタンスをRectangle型として宣言した変数rに代入します。
※「メソッドを呼び出すためには、インスタンスをつくっておかなければならない」と書きましたが、実は不正解です。後述する「クラスメソッド」はインスタンスを作らなくても呼び出すことができます。インスタンスを作らないと呼び出せないメソッドを「インスタンスメソッド」と呼びます。
//クラス名 変数 = new クラス名(); Rectangle r = new Rectangle();
フィールドの読み書き
新しくインスタンスができたので、フィールドに値を代入して結果を出力してみます。
r.widthのようにRectangle型の変数rとRectangleクラスのフィールド名widthをドット(.)でつないで記述します。
//インスタンス:フィールドへのアクセス&メソッドの呼び出し //new演算子で作成したインスタンスを、Rectangle型として宣言した変数rに代入 Rectangle r = new Rectangle(); //フィールドへのアクセス r.width = 123; r.height = 45; //出力 System.out.println("幅は、" + r.width); System.out.println("高さは、" + r.height);
メソッドの呼び出し
先程は、幅と高さのフィールドに値を代入しました。すでにRectangleクラスで長方形の幅と高さを設定するsetSizeというメソッドを宣言していたので、setSizeをつかって長方形の大きさ、getAreaから長方形の面積を求めてみます。
//インスタンス:フィールドへのアクセス&メソッドの呼び出し //new演算子で作成したインスタンスを、Rectangle型として宣言した変数rに代入 Rectangle r = new Rectangle(); //メソッドの呼び出し r.setSize(100, 50); //出力 System.out.println("幅は、" + r.width); System.out.println("高さは、" + r.height); System.out.println("面積は、" + r.getArea());
完成
この例題ではRectangle.javaというクラスファイルに「長方形を定義するクラス」と「メインメソッドでJavaを実行するためのクラス」の2つのクラスを1つのファイルに記述しました。効率的なプログラミングを考えたとき、実装したい機能別にクラスファイルを作成し、最終的にメインメソッドで実行したほうが便利です。そういった考えのもとオブジェクト指向を目指したプログラミングをすることができます。
次回以降、オブジェクト指向なプログラミングに必要なクラスの継承などについて簡単に解説します。
//長方形を定義するクラス public class Rectangle{ //フィールドの宣言 //長方形の幅と高さを定義 private int width; private int height; //メソッドの宣言 //1:大きさを定義するメソッド public void setSize(int w,int h){ width = w; height = h; /* 以下のように記述することができます。 thisはインスタンス自身を表すものです。 メソッドの宣言のなかでは、フィールドやメソッドの前にインスタンスを指定する必要はありません。 コンパイラによって自動的にthisが補完されるからです。 */ //this.width = w; //this.height = h; } //2:面積を求めるメソッド public int getArea(){ return width * height; } //メインメソッド public static void main(String[] args) { //インスタンス:フィールドへのアクセス&メソッドの呼び出し //new演算子で作成したインスタンスを、Rectangle型として宣言した変数rに代入 Rectangle r = new Rectangle(); /*フィールドへのアクセス r.width = 123; r.height = 45; */ //メソッドの呼び出し r.setSize(100, 50); System.out.println("幅は、" + r.width); System.out.println("高さは、" + r.height); System.out.println("面積は、" + r.getArea()); } }
出力結果 -------------- 幅は、100 高さは、50 面積は、5000
<追記>アクセス修飾子について
クラスのフィールドやメソッドにもスコープがあります。publicやprivateは「アクセス修飾子」と呼ばれるものです。publicとした場合は、すべてのクラスからアクセス可能です。privateとした場合は、それが記述されたクラスのみアクセス可能で、他のクラスからはアクセスできません。すべてをpublicにすればよいかというと、そうではありません。スコープは大きいより小さいほうが良いです。必要に応じてスコープは大きくしましょう。