今回はJavaの最も重要な概念であるクラス、メソッドについて説明していきます。
私もまだまだプログラマーとしては発展途上で、こういう概念の話は言語化がむずい。
分かりにくい概念の話が多いですが、実装を経て「あーそういう事か」と分かればOKです。
もちろん、Hands On形式で実際にコードも書いていきますよ!
Javaの初心者向けおすすめ本
スッキリわかるJava入門 第3版 (スッキリシリーズ)
#クラス
オブジェクト指向の言語にはおおむねあると思っていますが、
Javaでは、ファイル1つのことを指す場合が多いです。
Javaでは
XXXX.javaというファイルを作った ⇔ XXXXというクラスを作った
という同値関係が、おおむね成立すると考えてもらってよいです。
※Pythonなどの場合は1ファイルの中に複数クラスを定義できたりします。
逆にFortranやCobolなどの言語はオブジェクト指向ではないので、
1ファイルにすべての処理を順に記載するといったこともあります。
クラスという概念は、1つの処理を複数のクラスに分割して、各クラスに処理を委譲するという事であり、
プログラムを簡単にかつ効率的に開発するうえで重要な考え方です。
##オブジェクト指向
オブジェクト指向とは、簡単に言うと、「処理とデータを同時に部品として扱う」ようなことと考えてください。
###料理で例える
カレーを作るという処理を考えたときに
- カレーを作れと支持する人
- 野菜を洗う人
- 野菜を切る人
- 肉を切る人
- 煮込む人
- 盛り付ける人
のようなステップ(人)によって実現します。
家で作るときは一人でやると思いますが、
プログラムの世界では、分業させた方がきれいで読みやすく保守しやすくなる方が多いので分けました。
この時「処理とデータを同時に部品として扱う」に従えば
- 野菜を洗う人
では
クラス:「野菜を洗う人」
データ:「野菜」
処理:「洗う」
となります。
- 「野菜」はJavaではフィールドというもので表現します。(必ずフィールドが必要なわけではありません)
- 「洗う」はJavaではメソッドというもので表現します。
これによって、
クラス内に、フィールドとメソッドを定義することで「野菜を洗う人」というオブジェクトを定義するためのクラスが実装できるわけです。
※たとえが悪いと思うので後出の実装部分で実際のJavaで詳しく見ていきましょう。
ちなみに、フィールドは例では使っていませんが。。
#メソッド
Javaのメソッドは前出の通り、処理を表現するものです。
メソッドを使うメリットとして
- 処理を使いまわすことが可能で、コードが見やすく、書きやすい
- 修正箇所が限定的になる
例を見た方が良いので後出の実装部分で実際のJavaで詳しく見ていきましょう。
#プログラム実装
それでは、今回は、渡した数字に対して、四則演算をして、集計をするようなプログラムを書いていきます。
仕様
1、2つの数字、a,bに対して、四則演算をしていく(今回は足し算(+2)と掛け算(×2)だけにします)
2、四則演算した2つの数字を最後に足し算して合計値を表示する。
それでは書いていきます。
まずはCalculationMainクラスを作成しましょう。
パッケージはどこでも構いません。
クラスの作り方を忘れた場合はVol.2を参照してください
package calculation;
public class CalculationMain {
}
今回はsrc/main/javaの下にcalculationパッケージを作成し、そこにクラスを作成しました。
次に2つの数字a,bを定義していきます。
package calculation;
public class CalculationMain {
public static void main(String[] args) {
int a = 1;
int b = 2;
}
}
お決まりのpublic static void メイン あーぐすを実装します。これもメソッドです。
その中にa,bの2つのint(数値)型を定義します。今回は1,2でいきます。
続いて、四則演算をしていきますが、ここで役割を分けるために四則演算専用クラスを作っていきます。
私と同じようにしている場合はcalculationパッケージの下にserviceパッケージを作成し、その下にCalculationクラスを作成します
- calculationを選択し右クリックから New > other 選択します
- packageと入力し Java > packageを選択しNextを押下します。
- Nameにcalculationはすでに入っていると思うのでcalculation.serviceとします。
- Finishで作成完了です。
すると、calculationのしたにserviceというフォルダらしきものができたことがわかると思います。
このように見えていない場合は、package explorerのところにある3点アイコンみたいなやつを選択して以下の画像のようにHierarchicalを選択すればOKです。ただここに関しては個人の好き好みがあると思うのでどちらでもOKです。
ではクラスを作りましょう。serviceパッケージの下に以下のようなクラスができたかと思います。
package calculation.service;
public class Calculation {
}
##足し算のメソッド
ここに四則演算をするためのメソッドを作っていきます。
まずは足し算用のメソッド
package calculation.service;
public class Calculation {
public int add(int num) {
}
}
新出の知識を抑えてください。
メソッドは
public [返り値の型] メソッド名前([引数の型 引数名,..])
で記述します。
[返り値の型]:voidは返り値なし、それ以外は指定に従って値を返します。
[引数の型 引数名,..]:型と引数の名前を指定します。複数指定が可能です。
ここで、今**add(int num)**の部分に赤線が出ていると思います。
マウスを持っていくと、なぜ赤線が出ているか理解できます。
そのとおり、返り値にvoid以外を指定するとreturnつまり値を返す記述が必要になります。
選択肢の中にあるAdd return statumentを選択してください。
すると、勝手に**return num;**が書かれたと思います。
package calculation.service;
public class Calculation {
public int add(int num) {
return num;
}
}
続いて足し算(+2)なのでもうadd2という名前にしてしまいましょう。
そして、引数のnumに2を加算して返すように書くと
package calculation.service;
public class Calculation {
public int add2(int num) {
return num + 2;
}
}
これで2を足すメソッドができました。
##掛け算のメソッド
次に掛け算のメソッドを書いていきます。
名前はmultiply2としましょう。
package calculation.service;
public class Calculation {
public int add2(int num) {
return num + 2;
}
public int multiply2(int num) {
return num;
}
}
知ってる人はいますかね?掛け算は*****を使うので以下で完成です。
package calculation.service;
public class Calculation {
public int add2(int num) {
return num + 2;
}
public int multiply2(int num) {
return num * 2;
}
}
最後に、仕様2の集計するメソッドを作ります。名前はaggregateとかで。
package calculation.service;
public class Calculation {
public int add2(int num) {
return num + 2;
}
public int multiple2(int num) {
return num * 2;
}
public int aggregate(int a, int b) {
return a + b;
}
}
もう余裕ですよね?
2つの値を足しすので、引数には2つの値を指定します。
それでは最後にオブジェクト指向らしさを出す作業、CalculationMainのa,bに対し、このメソッドを追加って最後まで実装していきます。
CalculationMainを開いてください。
まずCalculationクラスの中のメソッドを使う場合、外部クラスで直接呼べないので、呼ぶために以下のように書きます。
package calculation;
import calculation.service.Calculation;
public class CalculationMain {
public static void main(String[] args) {
int a = 1;
int b = 2;
Calculation calc = new Calculation();
}
}
new を使って書いています。現場では「Newする」と言ったりもしますが、
Calculationクラスの形を持ったオブジェクトをインスタンス化するというのがたぶん正しい表現です。
要するに初期化して使えるようにするみたいなイメージです。
前出の料理の例でいえば
- 辛口のカレーを作る
- 甘口のカレーを作る
それぞれでNewが必要になる可能性があります。
(同じ鍋を使ったら甘口なのに中辛になっちゃうから一回鍋を洗うか、新しい鍋を使う的なイメージ)
フィールドがなくメソッドだけのクラスをNewする時には改めてNewしないで使うことができる場合も多いです。
ここら編のインスタンス化の詳細は参考書籍に譲ります。(直近影響はないと思うので、いつかちゃんと勉強して整理するつもり)
そして、a,bそれぞれに仕様通りの演算をします。
package calculation;
import calculation.service.Calculation;
public class CalculationMain {
public static void main(String[] args) {
int a = 1;
int b = 2;
Calculation calc = new Calculation();
int aAdd2=calc.add2(a);
int bAdd2=calc.add2(b);
}
}
まず、a,bにそれぞれ2を足します。
Calculation型のcalcというオブジェクトのadd2メソッドを使う場合はこのように書きます。
同様に掛け算と、集計もやってみます。
package calculation;
import calculation.service.Calculation;
public class CalculationMain {
public static void main(String[] args) {
int a = 1;
int b = 2;
Calculation calc = new Calculation();
int aAdd2 = calc.add2(a);
int bAdd2 = calc.add2(b);
int aMultiply2 = calc.multiple2(aAdd2);
int bMultiply2 = calc.multiple2(bAdd2);
int result = calc.aggregate(aMultiply2, bMultiply2);
}
}
こんな感じで書けると思います。
最後にこんっソールに結果を表示したいので
System.out.println(result);
を入れて完成です。
package calculation;
import calculation.service.Calculation;
public class CalculationMain {
public static void main(String[] args) {
int a = 1;
int b = 2;
Calculation calc = new Calculation();
int aAdd2 = calc.add2(a);
int bAdd2 = calc.add2(b);
int aMultiply2 = calc.multiple2(aAdd2);
int bMultiply2 = calc.multiple2(bAdd2);
int result = calc.aggregate(aMultiply2, bMultiply2);
System.out.println(result);
}
}
結果はどうなるか予想しておきましょう。
a = 1 , b = 2
(a + 2)* 2 = 6
(b + 2)* 2 = 8
result = (a + 2)* 2 + (b + 2)* 2
より
∴ result = 14
では実行してみてください。実行方法は前回Vold.2と同様です。
確かに14になりましたよね?
a,bの値を変えて試してみてください。
#最後に
今回学んでほしかったのは
- CalculationMainクラスが、「処理を実行する役割」
- Calculationクラスが、「計算を実行する役割」
であること
- add2メソッドが計算の中でも2を加算する役割
- multiply2メソッドが計算の中でも2を掛け算する役割
- aggregateメソッドが計算の中でも2つの数字を足す役割
というように細かく処理の担当を分けたりすることで、
例えば、
「今、最初に2足してるけど、3にしといて」という仕様変更が入っても
メソッドに変えておけば1か所直せばいいのです。メソッドになってないと2か所直す必要があります。
今回のコードは簡単ですが、もっと大規模になってくると、仕様変更で膨大な修正をしなければならないみたいなことも起きてくるので、
- 適切にメソッドを切り出す(出来るだけ小さくする)
- クラスやメソッドの役割を明確にしておく
ということを学んでもらえていればいいかなと思います。