本稿は、プログラミング未経験で新人研修でプログラミングをやらされている皆様へ(3)の続きです。
メソッドを作成して、重複を減らす
でさぁ、ここまでなんとなく書いてきたけど、System.out.println()
って何なの? 未だに説明がないんだけど。……と、疑問をお持ちの皆様、ついにここで説明します。これはメソッドと呼ばれるもので、それを呼び出しているんです。
同じ処理を何回も書くのは苦痛……
こんな計算になんの意味があるのかは分かりませんが、「2と3と5と7と11と13の、それぞれを二乗した結果の合計を求めなさい」というお題のプログラムを考えてみてください。数字の増え方が一定ではないので(あと、配列をまだ勉強していないので)、for
ループは使用できません。だから、こんなプログラムになります。
class SumOfPrimeSquare {
public static void main(String[] args) {
int sum = 0;
sum += 2 * 2;
sum += 3 * 3;
sum += 5 * 5;
sum += 7 * 7;
sum += 11 * 11;
sum += 13 * 13;
System.out.println(sum);
}
}
あ、+=
は、右辺の値を左辺の変数に足し合わせるという意味です。sum += 2 * 2;
はsum = sum + 2 * 2;
と同じ結果になります。
で、このプログラムは、2 * 2と書くつもりが2 * 3とか書いちゃいそうで怖いです。だから、変数を使用して間違いが発生する可能性を減らしてみましょう。
class SumOfPrimeSquare {
public static void main(String[] args) {
int sum = 0;
int x = 2;
sum += x * x;
x = 3;
sum += x * x;
x = 5;
sum += x * x;
x = 7;
sum += x * x;
x = 11;
sum += x * x;
x = 13;
sum += x * x;
System.out.println(sum);
}
}
長いよ! 間違いが発生しづらくはなりましたが、同じ処理を何回も書くのが面倒くさくなってしまいました。x
に値を設定して、その二乗を計算してsun
に足し合わせるという処理は、毎回同じですもんね。こんなときは、メソッドが役に立ちます。
メソッドを作成する
実は今までも皆様はメソッドを作成していて、それはpublic static void main(String[] args) {}
の部分です。main
の部分がメソッドの名前、括弧の中が引数、中括弧の中がメソッドの処理となります……と言われてもなんだかわからないので、具体的なコードで説明とさせてください。
class SumOfPrimeSquare {
public static void main(String[] args) {
int sum = 0;
sum += square(2); // squareメソッドを使用して、2の2乗を足す
sum += square(3);
sum += square(5);
sum += square(7);
sum += square(11);
sum += square(13);
System.out.println(sum);
}
// 2乗した結果を返すメソッド
static int square(int x) {
return x * x;
}
}
今回作成したメソッドは、プログラムの以下の部分です。
static int square(int x) {
return x * x;
}
メソッドの最初のstatic
はとりあえずおまじないだと考えてください(後でクラスと一緒に説明します)。次のint
は、メソッドで処理をした結果(メソッドの戻り値と呼びます)の型です。今回はint
の値の2乗を計算するメソッドなので、メソッドで処理をした結果もint
になりますから、int
を指定します。square
はメソッドの名前で、処理内容が分かる名前を自由に付けてください。今回は、二乗を計算するメソッドなので、英訳してsquare
にしました。
括弧の中は、メソッドの処理の中で必要となる変数(メソッドの引数と呼びます)を記述します。二乗するにはどの数を二乗するのかという情報が必要なので、int
型のx
という変数を書きました。変数なので、名前は何でも構いません。a
でもnumber
でも何でも分かりやすければ可。数学では関数の引数はxとすることが多いので、今回は名前をx
にしてみました。
中括弧の中が処理です。x * x
で二乗を計算して、で、計算した結果を関数の処理結果とするためにreturn
しています。だから中括弧の中はreturn x * x;
となったわけですね。
メソッドを呼び出す
メソッドを作成しただけでは意味がないので、作成したメソッドを利用しましょう。メソッドを利用することを「呼び出す」と言います。
で、メソッドを呼び出しているのは、sum += square(2);
やsum += square(3);
の、square(2)
やsquare(3)
の部分です。呼び出される側であるメソッドを作成したときにメソッドの戻り値の型や引数の型を定義したことを、理解力は低いけど記憶力は良いコンピューターは覚えています。だから、メソッドを呼び出すときは型の記述は不要。メソッド名(引数に代入したい値)
とするだけでオッケーです。
square(2)
とすると、square
メソッドの一番目の引数であるint x
に2が代入されます。int x = 2;
と同じ処理が実行されるわけですね。で、そのx
を使用してx * x
した結果がメソッドの戻り値としてreturn
されるので、2の二乗の4になって、それをsum
に+=
すれば、これで2の二乗を足し合わせる部分まで終了。あとは続けてsquare(3)
やsquare(5)
と続けて処理をしていけば完了です。メソッドを使ったら、最初のプログラムより間違いの可能性が減って、2番目のプログラムよりも大分楽になったでしょ?
メソッド呼び出し時、引数へは値が「代入」される
……どうせならsum +=
の部分もメソッドの処理に含めちゃえば楽になるんじゃね? このようにお考えの方もいらっしゃると思いますが、残念ながらそれはうまくいきません。実際にプログラムを作って試してみましょう。
class SumOfPrimeSquare {
public static void main(String[] args) {
int sum = 0;
square(sum, 2);
square(sum, 3);
square(sum, 4);
square(sum, 5);
square(sum, 11);
square(sum, 13);
System.out.println(sum);
}
static void square(int sum, int x) {
sum += x * x;
}
}
メソッドは処理結果を返さなくても構いません。で、その場合は、メソッドの戻り値の型をvoid
にします。で、足し合わされる数を表現するint sum
と、二乗して足し合わせる数を表現するint x
を引数にしてみました。
さて、このプログラムを実行すると……0が表示されてしまいます。あれ? sum +=
しているのにどうして?
それは、メソッド呼び出しの際に、引数へは代入がなされるためです。以下のプログラムで考えてみてください。
class SumOfPrimeSquare {
public static void main(String[] args) {
int i = 0;
int j = i;
j += 1;
System.out.println(i);
System.out.println(j);
}
}
int i = 0;
で、変数i
の値は0になります。int j = i;
では、変数j
にi
の値を代入しているので、j
の値は0になります。で、その後、j += 1;
で、j
の値は1を足されて、0 + 1の結果である1になります。ここで重要なのは、変数j
には変数i
の「値」が代入されただけで、変数i
そのものとは無関係であることです。だから、その後のSystem.out.println(i);
ではj += 1;
したこととは無関係で、変数i
の値である0が表示され、System.out.println(j);
では変数j
の値である1が表示されます。
考えてみれば当たり前ですよね。代入がこのような動作になっていないと、int j = i + 1;
と書いたときの動きが、わけわからなくなっちゃいますもん。
で、これは引数でも同じです。square(sum, 2)
したときの動作は、square
メソッドの一番目の引数のsum
に、呼び出し側のsum
(同じ名前なので分かりづらいですけど、呼び出し側と呼び出される側では同じ名前でも別の変数になります。詳細は、次の章で説明するスコープまでお待ちください)の値を代入し、2番目の引数のx
に2を代入しています。値が代入されただけなので、呼び出されたメソッドの中で引数のsum
にx
を二乗した結果を足し合わせても、呼び出し側の変数sum
の値は変化しません(先のプログラムで、j += 1;
しても変数i
に影響がなかったのと同じ)。
だから、呼び出し側の変数sum
の値は0のまま変化せず、だから最後のSystem.out.println(sum);
で0が表示されたというわけ。
なんでそんな面倒な作りになっているんだと感じた方がいらっしゃるかもしれませんけど、これは、そのような作りの方がプログラミングが楽になるためです。詳細は次の章でご説明しますが、とりあえずは、呼び出される側のメソッドの引数は、呼び出す時に指定した値や変数の値が代入されるだけなのだと覚えておいてください。
ともあれ、その動作を理解してしまえば、メソッドはとても便利です。メソッドを活用したプログラムを作成してみてください。お疲れさまでした。
……ごめんなさい。枕であげたSystem.out.println()
について書くのを忘れていました。実はこれ、Javaを作った人が作成してくれたメソッドなんです。今回作成したsquare()
メソッドよりちょっと中身は複雑ですけど、でも、同じメソッドなんですよ。我々は、今までSystem.out.println()
でメソッドを呼び出して、画面への表示をしていたわけですな。
プログラミング未経験で新人研修でプログラミングをやらされている皆様へ(5)に続く予定です。