Java メソッドとクラス
Java SE 8
メソッド
クラス内でのメソッドの定義
public static 戻り値型 メソッド名(仮引数,...){ return 戻り値; }
mainメソッドからの呼び出し
メソッド名(実引数,...);
クラス
クラスは設計図で、通常はその実態であるインスタンスをnewすることで、そのインスタンスが持つフィールドやメソッドを用いる。
フィールド
クラスには、それぞれのインスタンスがもつことのできるフィールドと呼ばれる変数を複数定義できる。
フィールドはクラス宣言の下に書く。
public class Rectangle{ //フィールド private int tate; private int yoko; }
クラスメソッド
クラスには、それぞれのインスタンスがもつことのできるクラスメソッドと呼ばれるメソッドを複数定義できる。
クラスメソッドではフィールドの値を使って計算したり、フィールドの値を出力したりすることができる。
クラスメソッドにはstaticがつかない。
public class Rectangle{ private int tate; private int yoko; //クラスメソッド public int getArea(){ return tate * yoko; } public void show(){ System.out.println("tate:"+tate+", yoko:"+yoko+", area:"+getArea()); } }
コンストラクタ
インスタンスを作成するとき、初期化処理を行う特別なメソッドであるコンストラクタが呼び出される。
ひとつもコンストラクタが書かれていない場合、コンパイラがデフォルトコンストラクタを作成する。
コンストラクタ名はクラス名と同じものを使う。
Eclipseでは、ソース、フィールドを使用してコンストラクターを生成、などで自動生成処理が行える。
コンストラクタの仮引数の型や個数を変えて複数定義しておくことで、仮引数の型や個数に応じて異なるコンストラクタを呼び出すクラスになる。
public class Rectangle{ private int tate; private int yoko; //コンストラクタ public Rectangle(){ this.tate = 5; this.yoko = 15; } public Rectangle(int tate, int yoko){ this.tate = tate; this.yoko = yoko; } public int getArea(){ return tate * yoko; } public void show(){ System.out.println("tate:"+tate+", yoko:"+yoko+", area:"+getArea()); } }
new
メインメソッドでnewすることでインスタンスを作成し、フィールドやクラスメソッドを利用できるようになる。
public static void main(String[] args){ Rectangle r = new Rectangle(10, 20); r.show(); }
newされるとコンストラクタに仮引数の10と20が渡され、ローカル変数rが参照するインスタンス自身のフィールドのtateに10、yokoに20をそれぞれ代入する。
r.tate = 100;
のように記述するとpublicなフィールドにアクセスできてしまう。それを避けるためにフィールドはprivateで定義する。
r.show();
でRectangleクラスのshowメソッドを呼び出すことができる。
show()では自身のフィールドと、getAreaメソッドを使って計算した面積の値を出力する。
getArea内で計算しているのはthis.tateとthis.yokoだが、ここはあえてthisを書かなくても動く。
コンストラクタ内では、フィールドのtateと仮引数のtateを区別するためにthisを書いている。
HAS-A関係
フィールドに別のクラスのインスタンスをもつクラスを作成することができる。
基本的に、クラスがもつフィールドは、そのクラス内で処理する。
継承
クラス作成時に「extends クラス名」を書き加えると、該当クラスのスーパークラス(親)を継承したサブクラス(子)を作ることができる。
public class NamedRectangle extends Rectangle{ //追加するフィールド String name; //コンストラクタ public NamedRectangle(String name){ super(); this.name = name; } public NamedRectangle(String name, int tate, int yoko){ super(tate, yoko); this.name = name; public static void main(String[] args){ NamedRectangle nr = new NamedRectangle("one", 10, 20); nr.show(); } }
コンストラクタでは、親のコンストラクタを呼び出せるsuper();を使用している。
子にはshowメソッドはないが、親のshowメソッドを利用することができる。
オーバーライド
親のもつメソッドと同名で異なる動作のメソッドを子に作ることができる。
public class NamedRectangle extends Rectangle{ int tate; int yoko; String name; public NamedRectangle(String name) { super(); this.name = name; } public NamedRectangle(String name, int tate, int yoko){ super(tate, yoko); this.name = name; } //ここでshowメソッドをオーバーライド @Override public void show() { System.out.println("name:"+name+", tate:"+tate+", yoko:"+yoko+", area:"+getArea()); } public static void main(String[] args) { NamedRectangle nr = new NamedRectangle("one", 10, 20); //ここで呼び出されるのは、オーバーライドされたshowメソッド nr.show(); } }
抽象クラス
クラス定義時にabstractをつけると、実際の処理を書かない抽象メソッドをもつ抽象クラスを書くことができる。
抽象クラスは継承した子クラスでコンストラクタを定義し、メソッドをオーバーライドすることでnewできるクラスになる。
抽象クラス自体をnewすることはできない。
abstract class クラス名{ abstract 戻り値型 メソッド名(仮引数,...); }
インタフェース
インタフェースは-ableという名前をつけることが多い。
インタフェースの宣言時はclassではなくinterfaceと書く。
中には抽象メソッドを書き、実際の処理は書かない。このときabstractは省略される。
public interface Lockable{ boolean lock(); boolean unlock(); }
インタフェースはクラス宣言時にimplementsで実装し、インタフェースがもつ抽象メソッドをすべてオーバーライドする。
public class Safe implements Lockable{ @Override public boolean lock(){ return true; } @Override public boolean unlock(){ return false; } public static void main(String[] args){ Safe sf = new Safe(); System.out.println(sf.lock()); System.out.println(sf.unlock()); }
上記はlock()はtrueを返し、unlock()はfalseを返すだけのプログラム。
Comparableインタフェースを実装すると指定の比較方法で比較処理を行えるクラスが作れるようになる。
参考
なぜ抽象クラス(Abstract)を実装するのか - Qiita