== メソッド == クラスのもつ機能を定義したものをメソッドといいます。 メソッドはオブジェクトに対する(オブジェクトを利用した)処理を記述したものとも言えます。 Itemクラスのメソッドを定義してみましょう。 . {{attachment:itemClass.png}} 前回作成したプログラムはこのようでした。 {{{#!java public class Item { String name; int price; public static void main(String[] args) { Item a, b, c, d; a = new Item(); a.name="りんご"; a.price=100; b = new Item(); b.name="おにぎり"; b.price=120; c = new Item(); c.name="お茶"; c.price=150; System.out.printf("%s %d\n", a.name, a.price); System.out.printf("%s %d\n", b.name, b.price); System.out.printf("%s %d\n", c.name, c.price); } } }}} 22~24行目に各変数の指しているオブジェクトの値を表示するためのprint文があります。 <
>この部分をメソッドを使って書き直します。 ---- === メソッドの定義 === Item.javaにshowという名前のメソッドを追加します。 showメソッドの定義は4行で書けます。 {{{#!java void show() { System.out.printf("%s %d\n", this.name, this.price); } }}} このメソッドは指定されたインスタンス内の変数の値を表示するものです。 <
>値を返さないので型はvoidです。 これを属性の定義の前に追加します。 ---- === メソッドの利用 === 値を返さないメソッドの使い方は '''インスタンス.メソッド();''' です。 {{{ a.show(); }}} のように、インスタンスとメソッド名をピリオドでつなぎ後ろに括弧を書きます。 void(値を返さない)型のメソッドの場合 インスタンスxxxに対してメソッドyyy()を行う のように解釈すればよい。 この場合は「インスタンスaに対してshow()を行う」と読めます。 最初のプログラムでprint文で書いていたところをすべて、この形に書き直します。 {{{#!java public class Item { String name; int price; void show() { System.out.printf("%s %d\n", this.name, this.price); } public static void main(String[] args) { Item a, b, c, d; a = new Item(); a.name="りんご"; a.price=100; b = new Item(); b.name="おにぎり"; b.price=120; c = new Item(); c.name="お茶"; c.price=150; a.show(); b.show(); c.show(); } } }}} ---- === メソッドの動作 === メソッドが  インスタンス.メソッド(); として呼び出されると、このときのインスタンスの値が this に対応付けられてから、 メソッド本体が実行されます。 25行目の . a.show(); ではaの値がthisに渡されて実行されるので、aが参照しているItemインスタンス内の変数の値が表示されます。 . {{attachment:itemObject.png}} 26行目の . b.show(); ではbの値がthisに渡されて実行されるので、bが参照しているDrinkインスタンス内の3つの変数の値が表示されます。 ---- === 値を修正するメソッド === メソッド内で、thisが指しているオブジェクト内の変数の値を修正することもできます。 例としてsetYoryoメソッドを示します。 {{{#!java void setYoryo(int ryo) { this.yoryo = ryo; } }}} このメソッドは引数をとるので、呼び出し側でも引数の指定が必要です。 mainメソッド内で {{{ b.setYoryo(250); }}} を行うと、 bの指しているオブジェクト内の変数yoryoの値が250に修正されます。 ---- === 値を返すメソッド === 値を返すメソッドは次のように記述します . メソッド定義の先頭で返す型を指定 . メソッド本体ではreturn文を使って値を返す {{{#!java int getYoryo() { return this.yoryo; } }}} . この例では値を返すことしかしていませんが、通常はその前に計算などの処理が入ります。 値を返すメソッドは計算式の中で使えます。 呼び出し方は同じです。 {{{ System.out.println( a.getYoryo() ); }}} ----- === setYoryo(), getYoryo() === こんなメソッドを使わなくても、オブジェクト内の変数を直接参照すれば同じ処理が簡単に書けます。 小さなプログラムの場合はそれでかまいませんが、 大きなプログラムや堅牢性が要求される場合には、この形のメソッドが多用されます。 値の参照や修正をメソッドを使って行うようにすれば、 オブジェクトの状態をすべてクラス内で管理できるからです。 ---- === this === thisはキーワードです。 変数のように見えますが代入することはできません。 あいまいさが無いときは'''this.を省略'''することができます。 このページで示したメソッドではthis.がなくてもどの変数を指しているか明らかなので省略して {{{#!java void disp() { System.out.printf("%s \\%d %d ml\n", namae, kakaku, yoryo ); } }}} のように書けます。 thisを使って次のように書くこともしばしば行われます。 {{{ void setYoryo(int yoryo) { this.yoryo = yoryo; } }}} yoryoという同じ名前がありますがthisを使うことで区別ができます。 . yoryoは引数 . this.yoryoはインスタンス内の変数 ----- === メソッドの継承 === スーパークラスで定義されたメソッドはサブクラスでも利用できます。 {{{#!java public class Item { ... void dispName() ... } }}} 例えば、スーパークラスであるItemクラスでメソッドdispName()が定義されている時を考えます。 Drinkクラスのインスタンスに対してdispName()メソッドの呼び出しが行われたらどうなるでしょうか。 サブクラスであるDrinkクラスでメソッドdispName()が定義されているかどうかで処理が異なります。 (1)DrinkクラスでメソッドdispName()が定義されていないとき スーパークラスであるItemクラスで定義されているメソッドが使われます。 (2)DrinkクラスでメソッドdispName()が定義されているとき Drinkクラスで定義されているメソッドが使われます。 スーパークラスで定義されているメソッドと同じ名前のメソッドを サブクラスで再定義することもできます。 この場合サブクラスで定義したメソッドが優先されます。(2)の場合です。 これをメソッドの'''オーバーライド'''といいます。 どのクラスのメソッドが実行されるのか 1. インスタンスの属するクラスに対応するメソッドがあれば、それを実行する。 1. 無いときはスーパークラスの同じ名前のメソッドを探して、それを実行する。 1. 見つからないときは、親の親の親...と順に探します。 1. どうしても見つからないときはエラーになります。