概要
メソッドとは何か?
また使い方をわかり易く説明します。
メソッドとは?
固く言うと、一連の処理を一つにまとめたものです。
平たく言うと、何らかの処理を1つにまとめたものです。
例
System.out.printlnメソッドを見てみましょう。
よく使うprintlnメソッドは以下のようになっています。
1 2 3 4 5 6 7 8 |
// PrintStream.class public void println(String x) { synchronized (this) { print(x); newLine(); } } |
これを見ると、printlnメソッドの中にもメソッドがあることがわかると思います。
・printメソッド :引数(渡された値)を表示する
・newLineメソッド:改行
つまり、printlnメソッドは「引数の表示した後に改行する」メソッドであることがわかります。
このように、メソッドは一連の処理がひとまとめになっています。
引数とは?
メソッドに渡す値のことです。
引数がないメソッドもあります。
また、引数の数が可変長(引数の数が変わる)という指定方法もあります。
引数を与えることでメソッドの動作に何らかの影響を与えることができます。
引数が無い場合は、メソッド単独で動作します。
引数なしメソッド
例えば、printlnメソッドには引数がないものが用意されています。
処理は改行だけであり、引数を必要としていません。
1 2 3 4 5 6 7 8 |
// 呼び出し System.out.println(); // PrintStream.class // メソッドの中の処理 public void println() { newLine(); } |
引数あり
引き続きprintlnメソッドを例にします。
引数にString型の文字列を扱ったり、int型の数値を扱えるメソッドなどが用意されています。
これらはメソッド内で引数を扱う処理内容になっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 呼び出し元 System.out.println("コンソール出力"); System.out.println(100); // PrintStream.class // メソッドの中の処理 public void println(String x) { synchronized (this) { print(x); newLine(); } } public void println(int x) { synchronized (this) { print(x); newLine(); } } |
引数あり(可変長)
可変長とは、長さや大きさが決まっていないという意味です。
引数で可変長という場合、引数の数が決まっていないという意味になります。
例として、Stringクラスのformatメソッドを見ていきます。
1 2 3 4 5 6 7 8 |
// 呼び出し元 System.out.println(String.format("%s %s %d", "1つ目", "2つ目", 3)); // String.class // メソッドの中の処理 public static String format(String format, Object... args) { return new Formatter().format(format, args).toString(); } |
formatメソッドに引数として与えた値と、対応する型と変数名についてです。
・”%s %s %d” :フォーマットを指定している部分(String format [第1引数])
・”1つ目”, “2つ目”, 3 :可変長な引数の部分(Object… args [第2引数以降])
⇒「…」は配列の[](角カッコ)と同じ意味です。
つまり、第2引数以降は全てObject型配列のargsという変数名に格納されます。
このメソッドの場合、第2引数以降の3つの値が、フォーマットとして指定した「”%s %s %d”」の順番に対応した形で以下のように出力されます。
1 |
1つ目 2つ目 3 |
シグネチャとは?
シグネチャとは、メソッド名、引数の型、引数の数で構成されるひとまとまりのことです。
以下は、printlnメソッドの例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// String.class // 引数なしのシグネチャ public void println() { newLine(); } // 引数1つでint型のシグネチャ public void println(int x) { synchronized (this) { print(x); newLine(); } // 引数1つでString型のシグネチャ public void println(String x) { synchronized (this) { print(x); newLine(); } } |
オーバーロードとは?
シグネチャがわかるとオーバーロードがわかるようになります。
オーバーロードとは、1つのクラスに同じ名前のメソッドを複数定義することです。
シグネチャの引数の型と数が異なる同名のメソッドによって、別のメソッドとして機能させることができます。
また、引数の型と数が同じでも、並び順が異なることもオーバーロードできる条件になります。
以下のようなクラスで確認していきましょう。
引数の型、数、並び順が異なるoutメソッドを複数定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public class OrverRoad { private String msg; public OrverRoad(String msg) { this.msg = msg; } // 引数なし public void out() { System.out.println(msg); } // 引数あり(1つ:String) public void out(String addMsg) { System.out.println(msg + " " + addMsg); } // 引数あり(1つ:int) public void out(int num) { System.out.println(msg + " " + num); } // 引数あり(2つ) public void out(String addMsg, int num) { System.out.println(msg + " " + addMsg + " " + num); } // 引数あり(2つ:並び順変更) public void out(int num, String addMsg) { System.out.println(msg + " " + num + " " + addMsg ); } } |
それぞれのメソッドを呼び出します。
実行結果をコメントで記載しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public static void main(String[] args) { // オーバーロードの例 OrverRoad orverRoad = new OrverRoad("NEWしました"); // 引数無し orverRoad.out(); // NEWしました // 引数あり(1つ:String) orverRoad.out("追加メッセージ"); // NEWしました 追加メッセージ // 引数あり(1つ:int) orverRoad.out(100); // NEWしました 100 // 引数あり(2つ) orverRoad.out("メッセージが先", 100); // NEWしました メッセージが先 100 // 引数あり(2つ:並び順変更) orverRoad.out(100, "メッセージが後"); // NEWしました 100 メッセージが後 } |
引数の型、数、並び順の違いで、実行されるメソッドが切り替わっていることがわかると思います。
オーバーロードはこのように、同名メソッドで複数の機能を実現できる仕組みになっています。
補足
シグネチャが同じで、メソッドの戻り値だけが異なる場合はオーバーロードできません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * 戻り値の型が、voidとStringの同一シグネチャは定義不可 /* // 引数あり(2つ:並び順変更) public void out(int num, String addMsg) { System.out.println(msg + " " + num + " " + addMsg ); } // 引数あり(2つ、並び順変更) // 「型 OrverRoad にメソッド out(int, String) が重複しています」 // というエラー表記がでます(Eclipseの場合) public String out(int num, String addMsg) { return this.msg + " " + num + " " + addMsg; } |
参考資料(Google Java Style Guide)
GoogleのJavaに関するコーディング規約です。
そこにメソッドについて共有しておきたい内容があったので転載致します。
(Google翻訳をベースに少し修正しています)
The order you choose for the members and initializers of your class can have a great effect on learnability. However, there’s no single correct recipe for how to do it; different classes may order their contents in different ways.
What is important is that each class uses some logical order, which its maintainer could explain if asked. For example, new methods are not just habitually added to the end of the class, as that would yield “chronological by date added” ordering, which is not a logical ordering.
3.4.2.1 Overloads: never split
When a class has multiple constructors, or multiple methods with the same name, these appear sequentially, with no other code in between (not even private members).
3.4.2クラス内の順序
クラスのメンバーと初期化子の順序は、可読性に大きな影響を与える可能性があります。ただし、それを行う方法についての正しいレシピは1つではありません。クラスが異なれば、コンテンツをさまざまな方法で並べ替えることができます。
重要なのは、各クラスが論理的な順序になっていることで、メンテナンスする人が尋ねられた場合に説明できます。たとえば、新しいメソッドはクラスの最後に習慣的に追加されてはいけません。これは「追加された日付による時系列」であり、論理的な順序ではありません。
3.4.2.1 オーバーロードされたメソッド群を分割しないこと
クラスに複数のコンストラクター、または同じ名前の複数のメソッドがある場合、これらは順番に表示され、間に他のコードはありません(プライベートメンバーも含まれません)。
要約します。
・クラスのメンバ(フィールド、メソッド)は論理的な並び順になっているべきである。
・新しいメソッドを最後に追加するのは慣習であって、論理的ではない。
・オーバーロードしたメソッドはひとまとまりにしておきなさい。
このようなことを学ぶことも良いコードを書くことにつながりますので、参考までに知っておいて頂ければと思います。
まとめ
- メソッドとは、一連の処理を一つにまとめたものです。
- 引数とは、メソッドに与える値のことです。
- シグネチャとは、メソッド名・引数の型・引数の数で構成されるひとまとまりのことです。
- オーバーロードは、同じメソッド名で複数の機能を持たせることができる仕組みのことです。
メソッドの引数の型と数、並び順で決まります。
コメント