この章では抽象メソッド(本体のないメソッド)の集まりである完全に抽象化されたクラスであるインタフェース
についてとりあげます
インタフェース
クラスの設計図のようなもので、クラスがどのような機能を持つべきかを定義しますが、具体的な実装は記述しません
インタフェースの特徴
次のような特徴があります
- クラスに実装を要求する抽象メソッド(具体的な処理が記述されていないメソッド)のみを定義できることにより、クラスがどのような機能を持つべきかを定める設計図のような役割を果たす
- 多重継承(複数のインタフェースを実装)ができることにより、クラスに多様性と柔軟性を与えることができる
- インタフェースは、抽象化とポリモーフィズムの原則を実現することで、クラスの実装を隠蔽し、オブジェクトの振る舞いを定義することができる
抽象クラスとの違い
抽象クラス
との違いは、抽象メソッドと定数しか持つことができず、具体的な処理内容は記述できないことです
抽象クラス
とインタフェース
の違いは以下の通りです
項目 | 抽象クラス | インタフェース |
---|---|---|
記述内容 | 抽象メソッド、具体的な処理 | メソッド宣言のみ |
継承 | 単一継承(あるクラスは1つの抽象クラスしか継承できない) | 多重継承(あるクラスは複数のインタフェースを実装できる) |
目的 | 共通処理の記述、クラスの設計 | 機能の保証、型の定義 |
※Java 8以降では、インタフェースにデフォルトメソッドを追加できるようになり、インタフェースにも一部の具体的な処理を記述できるようになりました
使い方
インタフェースの宣言は以下のように記述します
interface インタフェース名{
メソッドの宣言;
}
実装する場合は、以下のようにimplements
キーワードを使い記述します
class クラス名 implements インタフェース名{
クラスの内容
}
また、複数のインタフェースを実装する場合は、以下のように記述します
class クラス名 implements インタフェース名A,インタフェース名B{
クラスの内容
}
以下に、インタフェースを定義したサンプルプログラムを示します
interface IShape{
public int getColor();
public int getDot();
public void getDraw();
}
interface ICalculateArea{
public double getCalculateArea();
}
IShapeインタフェースには getColor(), getDot(), getDraw() という抽象メソッドを定義しています
ICalculateAreaインタフェースには、getCalculateArea()という抽象メソッドを定義しています
class ShapeLine implements IShape{
int color;
int dot;
double length;
ShapeLine(int color,int dot,double length){
this.color = color;
this.dot = dot;
this.length = length;
}
public int getColor(){
return this.color;
}
public int getDot(){
return this.dot;
}
public void getDraw(){
System.out.println("length=" + this.length);
}
}
class ShapeRectangle implements IShape,ICalculateArea{
int color;
int dot;
double width;
double height;
ShapeRectangle(int color,int dot,double width,double height){
this.color = color;
this.dot = dot;
this.width = width;
this.height = height;
}
public int getColor(){
return this.color;
}
public int getDot(){
return this.dot;
}
public void getDraw(){
System.out.println("width=" + this.width + " ,height=" + this.height);
}
public double getCalculateArea(){
return this.width * this.height;
}
}
ShapeRectangleクラスは IShape と ICalculateArea の2つのインタフェースを実装しています
そのため、IShape と ICalculateAreaの両方で定義されたメソッドを提供する必要があります
ShapeLineクラスはIShapeのインタフェースを実装していますので、IShapeで定義されたメソッドを提供する必要があります
public class Sample{
public static void main(String []args){
ShapeRectangle rect = new ShapeRectangle(0x0000ff,1,1.5,2.0);
rect.getDraw();
double area = rect.getCalculateArea();
System.out.println("area=" + area);
ShapeLine line = new ShapeLine(0x00ff00,1,3.3);
line.getDraw();
}
}
実行結果
width=1.5 ,height=2.0
area=3.0
length=3.3
ShapeRectangleクラスおよびShapeLineクラスのインスタンスを作成し、それぞれの関数を呼び出しています
一方、IShape型の変数を使って ShapeLineオブジェクトや ShapeRectangleオブジェクトを参照するポリモーフィズムの例を以下に示します
public class Sample{
public static void main(String []args){
IShape shape1 = new ShapeLine(1, 2, 10.0);
IShape shape2 = new ShapeRectangle(3, 4, 5.0, 8.0);
shape1.getDraw(); // length=10.0
shape2.getDraw(); // width=5.0 ,height=8.0
}
}
実行結果
length=10.0
width=5.0 ,height=8.0
【演習問題】
- 上のサンプルプログラムを実装してみましょう
- ShapeCircleクラスをIShape、ICalculateAreaから実装してみましょう
- 以下のようなWalletクラスとCreditCardクラスがあります。pay()メソッドをもったインタフェースIPaymentを作成しWalletおよびCreditCardクラスを書き換えてみましょう
class Wallet{
int amount;
Wallet(int amount){
this.amount = amount;
}
boolean pay(int money){
if(this.amount<money){
System.out.println("Not enough money left");
return false;
}else{
this.amount-=money;
System.out.println("The remaining balance is " + this.amount + " yen.");
return true;
}
}
}
class CreditCard{
String company;
String cardNo;
String name;
CreditCard(String company,String cardNo,String name){
this.company = company;
this.cardNo = cardNo;
this.name = name;
}
boolean pay(int money){
System.out.println("Credit card payment completed");
return true;
}
}
public class Main {
public static void main(String[] args) {
Wallet wallet = new Wallet(10000); // 財布インスタンスを作成し1万円入れる
wallet.pay(6000);
wallet.pay(5000);
CreditCard card = new CreditCard("Yamamoto","N社","1234567890");
card.pay(15000);
}
}
コメント