2014年9月26日金曜日

- メソッド - Java

今日は「メソッド」について学習する。
ここが、初学者にとっては、最初の難関になる。
(わたしは、ここで、数回、挫折した。)

しかし、今までずっと「メソッド」は使ってきている。

- 基本構造 - で説明したように



















メソッドの中に変数や、命令、分岐などを書いてきた。

今まで書いてきたものは、全て、「main メソッド」の中。
今日は、「main メソッド」以外のメソッドを作っていく。

「メソッド」は、複数の文をまとめて名前をつけたもの。
































mainメソッドは、どの順番で書いても、必ず初めに実行される。
メソッドはmainメソッド以外からでも呼び出せる。
各メソッドは、機能ごとにわけるといい。

mainメソッドに全て書くことも出来るけど、メソッドに細かく分けることによっていくつかメリットがある。

・mainメソッドで、分割したメソッドを呼び出して使用すると、コードがスッキリする。
・機能単位でメソッドを分割すると、全体の把握が容易になり、修正もしやすくなる。
・メソッドを繰り返し使用できるから、同じ処理を書く手間が省ける。


メソッドの使い方は、以下のとおり。






















定義して、呼び出す。
これが、基本だから、あとは細かい作法を理解するだけ。


package blog;

public class MethodConcept {

 // mainメソッドから、2つのメソッドを呼び出します
 public static void main(String[] args) {

  System.out.println("ここはメインメソッドです");

  System.out.println("メソッドを呼び出してみます");

  name();
  age();
 }

 public static void name() {
  String myName = "ともみ!!";
  System.out.println("ここは nameメソッドです");
  System.out.println("わたしの名前は" + myName + "です");
 }

 public static void age() {
  int myAge = 27;
  System.out.println("ここは ageメソッドです");
  System.out.println("年齢は" + myAge + "ですよー");
 }

}












引数

おそらく、ここから、難しくなってくる。

メソッドの定義、呼び出しの方法に書かれている、「引数」とは、なにか。

メソッドを呼び出す際に呼び出し元から渡される値のことを引数という。

文章だけだと、よくわからないかもしれない。


package blog;

public class Argument {

 // メインメソッドから、引数を1つだけ渡して実行するプログラム
 public static void main(String[] args) {

  System.out.println("メソッドを呼び出します");

  // Englishメソッドに "Hello" を渡して呼び出す
  English("Hello");
  // Japaneseメソッドに "こんにちは" を渡して呼び出す
  Japanese("こんにちは");
  // Germanyメソッドに "Guten tag" を渡して呼び出す
  Germany("Guten tag");

  System.out.println("呼び出し完了!!!");

 }

 // Englishメソッドを定義する
 // String型の文字列を1つ受け取る
 /*
  * 文字列変数 greetings の有効範囲はブロック内だけだから 
  * 別のメソッドで使われている greetings は別のもの
  */
 public static void English(String greetings) {
  System.out.println("英語での挨拶「" + greetings + "」");
 }

 // Japaneseメソッドを定義する
 // String型の文字列を1つ受け取る
 public static void Japanese(String greetings) {
  System.out.println("日本語での挨拶「" + greetings + "」");
 }

 // Germanyメソッドを定義する
 // String型の文字列を1つ受け取る
 public static void Germany(String greetings) {
  System.out.println("ドイツ語での挨拶「" + greetings + "」");
 }
}












この場合、呼び出すのは mainメソッド
受け取るのは Englishメソッド、Japaneseメソッド、Germanyメソッド。
呼び出し元(mainメソッド)から渡される値(引数)は
String型(文字列)の "Hello"、"こんにちは"、"Guten tag"


一番はじめに書いた MethodConceptクラスでは
引数を渡していないため

public static void main(String[] args) {
         name ( );
         age ( );
}

public static void name() {
            :
}

public static void age() {
           :
}
のように、メソッド名の後の ( ) に、何も入っていない。

















上の図のように、値は、0個~複数個、渡すことができる。


package blog;

public class MultipleArgument {

 // mainメソッドから、2つのメソッドに引数を渡して呼び出す
 public static void main(String[] args) {

  System.out.println("ファミコンで遊びます");

  System.out.println("モンスターを呼び出します");

  // slimeメソッドに、引数を2つ渡して呼び出す
  slime("スライム", 3);
  // dragonKingメソッドに、引数を3つ渡して呼び出す
  dragonKing("りゅうおう", 130, 140);

  System.out.println("モンスターをすべて呼び出しました");
 }

 // slimeメソッドを定義する
 // String型も文字列、int型の整数の2つを受け取る
 public static void slime(String name, int hp) {
  System.out.println(name + "が現れた!!!");
  System.out.println("体力は" + hp + "だ");

 }

 // dragonKingメソッドを定義する
 // String型の文字列、int型の整数を2つ、計3つを受け取る
 public static void dragonKing(String name, int hp, int atack) {
  System.out.println(name + "が現れた!!!");
  System.out.println("体力は" + hp + "だ!!");
  System.out.println("攻撃力" + atack + "だ!!");
 }

}















戻り値

これが、今日の山場。
これさえ理解できれば、じゅうぶん。
(わたしは、以前、理解することを諦めて、別のものを作り始めたら、理解できていました)


呼び出されたメソッドから、呼び出し元のメソッドに値を返すことを「値を戻す」という。
また、その値ことを、「戻り値」という。






















return 戻り値 ;
というのは、return文という。
return の横の 戻り値 が呼び出し元に戻せる値。
メソッドを終了させる役割もある。

また、一行目の 戻り値の型 というのは
return によって、戻される値と同じ型を指定する必要がある。

たとえば、
return 100; だと int
return "AIUEO" だと String


package blog;

public class ReturnValue {

 // lifeメソッドから、mainメソッドへ値を返して、何日生きてきたかを調べる
 public static void main(String[] args) {

  System.out.println("lifeメソッドを呼び出します!!");

  // lifeメソッドに int型の整数 27 , 365 を渡す
  // lifeday (中身は age * day) が返ってきて、allLife に代入される
  int allLife = life(27, 365);

  System.out.println("わたしは、おおまかに" + allLife + "日、生きてますよー");
 }

 // lifeメソッドを定義する。int型の整数を2つ受け取る
 public static int life(int age, int day) {
  // lifeメソッドが呼び出されると受け取った引数が代入される
  int lifeDay = age * day;
  // lifeメソッドが呼び出されると、 lifeday (戻り値)が返される。
  return lifeDay;
 }
}










オーバーロード

メソッドに同じ名前をつけることは基本的に出来ない。
例外的に、同じ名前のメソッドを定義することはできる。
それを、オーバーロードという。

方法は2つある。

・仮引数(受け取る変数のこと)の型が異なる場合
・仮引数の数が異なる場合


まずは、仮引数の型が異なる場合

package blog;

public class DifferentModel {

 // 同じ名前のメソッドを定義して、呼び出すプログラム
 public static void main(String[] args) {

  System.out.print("今週の");

  // 仮引数が String型,String型 の studyメソッドに文字列を渡す
  study("英語", "数学");

  // 仮引数が int型、int型 の studyメソッドに整数を渡す
  // allTime に time * day を戻り値として受け取る
  int allTime = study(6, 5);
  System.out.println(allTime + "時間です");
 }

 // String型 の studyメソッドを定義する
 public static String study(String subject1, String subject2) {
  System.out.println(subject1 + "と" + subject2 + "の勉強時間は");

  // 値を返さないので、 null を返す
  // ※値を返さないので、 本当は、void型のメソッドにしたほうがいい※
  return null;
 }

 // int型の studyメソッドを定義する
 public static int study(int time, int day) {
  // int型の studyメソッドが呼び出されると int型の整数を2つ受け取る
  // 整数を受け取った time*day が allTime に代入される
  int allTime = time * day;
  // return で allTime を呼び出し元に渡す
  return allTime;
 }

}











次に、仮引数の数が異なる場合


package blog;

public class DifferentNumber {

 // オーバーロードを使い、正方形、長方形、三角形の面積を求めるプログラム
 public static void main(String[] args) {

  int x = 4;
  int y = 8;
  int z = 2;

  // 1つの仮引数をもつdiagramメソッドに int型変数 x を渡し、area を受け取る
  // 受け取った値を squareArea に代入する
  int squareArea = diagram(x);
  System.out.println(squareArea);

  // 2つの仮引数をもつdiagramメソッドに int型変数 x ,yを渡し、area を受け取る
  // 受け取った値を rectangleArea に代入する
  int rectangleArea = diagram(x, y);
  System.out.println(rectangleArea);

  // 3つの仮引数をもつdiagramメソッドに int型変数 x ,y,zを渡し、area を受け取る
  // 受け取った値を triangleArea に代入する
  int triangleArea = diagram(x, y, z);
  System.out.println(triangleArea);

 }

 // int型のdiagramメソッドを定義し、xを受け取る
 public static int diagram(int x) {
  System.out.println("正方形の面積を求める");
  System.out.print("一片の長さが" + x + "cmの正方形の面積は");

  int area = x * x;
  // area を返す
  return area;
 }

 // int型のdiagramメソッドを定義し、x,yを受け取る
 public static int diagram(int x, int y) {
  System.out.println("長方形の面積を求める");
  System.out.print("縦が" + x + "cm,横が" + y + "cmの長方形の面積は");

  int area = x * y;
  // area を返す
  return area;
 }

 // int型のdiagramメソッドを定義し、x,y,zを受け取る
 public static int diagram(int x, int y, int z) {
  System.out.println("三角形の面積を求める");
  System.out.print("底辺" + x + "cm,高さ" + y + "cmの三角形の面積は");

  int area = x * y / z;
  // area を返す
  return area;
 }

}












引数、戻り値に配列を使う

メソッドの引数には、変数型だけでなく、配列型を使える。


package blog;

public class ArgumentArray {

 // 引数に配列を使って、整数を渡して出力するプログラム
 public static void main(String[] args) {

  System.out.println("素数をいくつか、あげてみます");

  // int型配列に、整数を代入する
  int[] array = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
  // primeNumberメソッドに、配列を渡して呼び出す
  primeNumber(array);
 }

 // int型配列を引数として受け取る primeNumberメソッドを定義する
 public static void primeNumber(int[] array) {
  // 何個目かを表す int型の整数を宣言して 1 を代入
  int turn = 1;
  // forループを使って、配列をまわす
  for (int number : array) {

   System.out.println((turn++) + "個目の素数は" + number);
  }
 }
}

















素数を出すプログラムは、今までの知識だけで作れるのですが、今回は、手打ちで!!
そのうち、書きます。

今まで、 int ~ としていたところを、
int [ ] ~ に変えると配列を渡せる。

ただ、配列を渡すときは、変数を渡すときとは、少し違う。

メソッドを呼び出すときに渡される変数は、変数そのものではなく、値である。
値そのものが渡されることを、値渡しという。
配列の場合は、値そのものではなく、要素のアドレスが渡される。
このように、引数に値ではなく、アドレスを渡すことを、参照渡しという。
このアドレス部分に関しては、別の機会に書きたい。

具体的にどういうことかというと。


package blog;

public class CallByReference {

 // 参照渡しの例
 public static void main(String[] args) {

  // int型配列 に 値を三つ代入する
  int array[] = { 10, 100, 1000 };
  // 配列をまわす
  for (int i : array) {
   System.out.println("mainメソッドでは" + i);
  }
  // testArrayメソッドに配列を渡す
  testArray(array);

  // 配列をまわす
  for (int i : array) {
   System.out.println("mainメソッドでは" + i);
  }
 }

 // int型配列を引数として受け取る testArrayメソッドを定義する
 // void型のメソッドなので、値を返さない(return文無し)
 public static void testArray(int[] array) {
  System.out.println("~【始】testArray【始】~");
  // for文で配列をまわす
  for (int i = 0; i < array.length; i++) {
   array[i]++;
   // 配列を表示
   System.out.println("testArrayメソッドでは" + array[i]);
  }
  // 値を返さずに終了
  System.out.println("~【終】testArray【終】~");
 }

}

















値を返していないのに、呼び出し元(mainメソッド)の配列の中身がかきかわっている。
なので、mainメソッドと、testArrayメソッドで、参照している配列は
全く同じものだということになる。
(変数を引数として受け取る場合だと、それぞれのメソッドで宣言している変数は同じ名前であっても別のもの。)

これは、戻り値に配列を用いる場合でも同様。


package blog;

public class ReturnValueArgs {

 // 戻り値に配列を使う
 public static void main(String[] args) {

  System.out.println("一週間は!");

  // dayメソッドに 7 を渡して、
  // 受け取った値(アドレス)を int型配列 day に格納
  int[] day = day(7);
  // 拡張for文を使って、配列をまわす
  for (int i : day) {
   System.out.println(i + "日!!!");
  }
 }

 // int型配列を返す dayメソッドを定義する
 // int week では引数を受け取る
 public static int[] day(int week) {

  // 7 を受け取った week を int型配列 newDay に代入する
  int[] newDay = new int[week];

  // for文で配列をまわす
  for (int i = 0; i < newDay.length; i++) {
   // 0から始まるため、 1 を足して、newDay[i] に代入
   newDay[i] = i + 1;
  }
  // 呼び出し元に newDay を返す
  return newDay;
 }
}




0 件のコメント:

コメントを投稿