2019/02/06
sponsored link
メンバメソッドとは?
前々回の【Java】オブジェクトって何?で、Humanクラスを書いて、それをnewすることでHumanオブジェクトを作りました。Humanクラスはこんなのでした。
Human.java
public class Human{ String name; int birthday; }
このクラスから作られたインスタンスはnameとbirthdayというパラメータを持っています。言い方を変えると、Humanクラスのメンバはnameとbirthdayの二つだけです。
今回はここに新たなメンバを追加していきたいと思います。nameとbirthdayは変数(パラメータ)ですが、今回新たに追加するメンバはメソッドです。
変数でもメソッドでもそのクラスのメンバの一員です。変数はそのオブジェクトのパラメータを表すのに対して、メソッドはそのオブジェクトの振る舞いを表します。
人間なら誰でも何かしら食べますよね。ということでHumanオブジェクトの振る舞いとして、eat()メソッドを追加します。
Human.java
public class Human{
String name;
int birthday;
void eat(){}
}
出来ました。
このメソッドは戻り値を返さないようにするので「void」をメソッド名の前につけて、「eat( )」その後ろに{ }波かっこを書きます。これはメソッドの定義の形ですね。その波かっこの中にこのメソッドの内容を定義するんでした(参考:【Java】 メソッドの定義と呼び出し)。
今までメソッドを定義する時は必ず「static」をつけていましたが、ここでは要りません。なぜか?このメソッドはstatic(静的)ではないからです。・・説明になってないですよね。これ非常に重要なポイントなのでまたの機会に詳しい説明をするのでここではとりあえず『eat()メソッドはstaticなメソッドではない』と思っていてください。
eat()メソッドの中身は今のところ何も定義していません。まずはこの形を理解してください。これでこのHumanクラスは3つのメンバを持つことになりました。変数nameとbirthday、それにeat()メソッドです。
さらにもう一つメンバを追加します。満腹度を示すパラメータです。満腹度は整数で表すことにしますのでint型の変数「manpukudo」をメンバに追加しましょう。名前がかっこ悪くて申し訳ないです。。いい英語が思いつかないので日本語で行きます。
Human.java
public class Human{
String name;
int birthday;
int manpukudo;
void eat(){}
}
メンバ変数とメンバメソッドは分けて書いた方が見やすいので、上の方にメンバ変数はかためて書いておきましょう。さらに間を一列空けて書いたりしたら見やすくてGood。
メンバメソッドを定義する
ではHumanクラスのメンバメソッドであるeat()メソッドを定義していきます。食べたらお腹が満たされるので、eat()メソッドが実行されると満腹度を表す「manpukudo」の数値が上がるようにします。なんぼ上がるかって?とりあえず適当に60上がることにしましょう。単位とか余計なことは考えずに。(笑)
Human.java
public class Human{
String name;
int birthday;
int manpukudo;
void eat(){
this.manpukudo += 60;
}
}
はい、出ました。「this」です。初心者を苦しめるやつです。と言ってもそんな大したことないのでサクッとやっつけましょう。
「this」は日本語で「これ」とか「この」という意味なのは皆さんご存知かと思いますが、この場合、「このインスタンス」という意味になります。そして「.」を日本語に訳すなら「の」という意味です。つなげて「this.」で「このインスタンスの」という意味になります。
つまりこのeat()メソッドの定義部分は「このインスタンスの満腹度を60上げる」という処理になります。
案ずるより生むが易しです。実際やってみましょう。Humanクラスは上記のように4つのメンバを持った状態です。mainメソッドを持つHumanTestクラスでこのHumanクラスをインスタンス化して、実際にeat()メソッドも使ってみます。ここからはHumanTestクラスですよ。ごっちゃにならないように。
HumanTest.java
public class HumanTest{ public static void main(String[] args){ Human human = new Human(); human.name = "ノブオ"; human.birthday = 19770101; Human human2 = new Human(); human2.name = "アヤネ"; human2.birthday = 20110101; human.eat(); //ノブオ1回目の食事 human.eat(); //ノブオ2回目の食事 human2.eat(); //アヤネ1回目の食事 } }
前回やりましたが、メンバ変数にアクセスするには、
オブジェクトが入った変数.メンバ変数
この形でした。実はメンバ変数であろうと、メンバメソッドであろうとこの形でアクセスすることができます。
オブジェクトが入った変数.メンバ
「human.eat()」でノブオさんが食事したことになります。同じく「human2.eat()」でアヤネさんに食事させたわけです。
上記ではノブオさんは2回も食事しています。アヤネさんは1回です。さて、それぞれの満腹度はどうなっているでしょうか?出力してみましょう。
HumanTest.java
public class HumanTest{ public static void main(String[] args){ Human human = new Human(); human.name = "ノブオ"; human.birthday = 19770101; Human human2 = new Human(); human2.name = "アヤネ"; human2.birthday = 20110101; human.eat(); //nobuo1回目の食事 human.eat(); //nobuo2回目の食事 human2.eat(); //ayane1回目の食事 System.out.print(human.name + "の満腹度:"); System.out.println(human.manpukudo); System.out.print(human2.name + "の満腹度:"); System.out.println(human2.manpukudo); } }
これで実行すると、
こうなります。
ノブオさんは2回食事したので満腹度が120になっています。アヤネさんは1回だけなので満腹度60です。
それぞれのインスタンスごとに満腹度というパラメータを持っていて、それぞれのeat()メソッドを実行することで、それぞれの満腹度を+60しているわけです。
Humanクラスのeat()メソッドを定義する時に使った「this.manpukudo += 60」とはそういうことです。
eat()メソッドは、自分自身のパラメータ(manpukudo)を60増やすという処理を行います。「自分自身の」という意味で「this.」が使われているわけです。
メンバ変数の初期値
ところで、2回食事をしたノブオが120で、1回食事をしたアヤネが60ということは、メンバ変数manpukudoの初期値は「0」だったということが分かりますね。
変数manpukudoは宣言はしましたが初期化していませんでした。このように、メンバ変数(パラメータ)を初期化せずにそのクラスをインスタンス化した場合、int型の変数は「0」で初期化されるというルールがあります。なので、manpukudoの初期値は「0」なんです。
さらに、boolean型のメンバ変数は「false」、String型はのメンバ変数は「null」(”空っぽ”の意)で初期化されるというのも決まっています。
なので、nameとbirthdayはインスタンスを作った時点では「null」と「0」なのですが、「human.name = “ノブオ”;」「human.birthday = 19770101;」でそれぞれの値を後から書き換えていることになります。
しかし、名前と生年月日って後から書き換えたりするのっておかしいと思いませんか?生年月日なんて途中で変わること絶対ないでしょうし。。
インスタンスを作る時点で、そのインスタンスが一体誰を表すものなのか?その人間の生年月日はいつなのか?は決まっているはずです。
名無しのインスタンスを作ってから名前と生年月日を入力するのではなく、「ノブオという名の1977年1月1日生まれの人間」を表すインスタンスを初期状態として作れたら一番いいと思いませんか?
それが実は簡単にできるんです。コンストラクタというのを使えば、インスタンスの初期状態を自由に操ることができます。次回、「コンストラクタって何?」で解説します。
今だけ→転職できなければ全額返金の「エンジニア転職保証コース」
絶対エンジニアになる!→テックエキスパート
フリーランスエンジニアの収入例を見てみる→レバテックフリーランス
コメント
初めまして。いつも勉強させてもらってます。
この例でthisを用いずに実行するとどうなるのでしょうか?
by 瀧川 2015/11/13 11:47
thisは省略しても問題ないことがほとんどです。
同じスコープ内に同名のローカル変数や仮引数がなければ。
thisを付けることで、インスタンスのフィールドを表す変数であることが分かるので省略しない方が可読性は上がると思います。
by Nobuo@管理人 2015/11/13 12:20
名前は生まれたあとに付けてもおかしくないような。。
by 匿名 2017/02/25 21:48
↑コンストラクタの実用性を兼ねた紹介への流れがあるおかげで
初心者にも分かりやすくなっている だから全然問題ない いいね?
>>管理人 実行環境から勉強まで本当にお世話になっております。
初心者にやさs…分かりやすいサイトをありがとうございます!
by 超初心者 2017/04/12 09:40
↑www
>>管理人 お世話になってます。
by 匿名 2017/07/15 21:03