각각의 인터페이스로 선언된 메소드는 상속 받은 클래스에서 반드시 구현해합니다.
아래의 예제는 다중 인터페이스와 송속이 동시에 적용된 예제 입니다.
public interface AirCon {
int MAX_TEMP = 30; // public final static 숨겨져 있음
int MIN_TEMP = 0;
void airConON(); // 상속 받은 클래스에서 기능을 완성해야 함
void airConOFF();
void setAirConTemp(int tmp);
}
public interface AutoDrive {
void autoDrvON(); // abstract가 생략 되어 있음
void autoDrvOFF();
}
public class Car {
protected int speed; // 같은 패키지와 부모 자식 관계에서 접근 가능
protected String color;
protected String year;
public Car() {
this.speed = 150;
this.color = "white";
this.year = "1970";
}
}
public class SportCar extends Car implements AirCon, AutoDrive {
private boolean isAirCon; // AirCon ON/OFF
private int setTemp;
private boolean isAutoDrv;
private int speed;
private String color;
private String year;
private boolean isTurbo;
public SportCar(boolean isAirCon, int setTemp,
boolean isAutoDrv, int speed, String color,
String year) {
this.isAirCon = isAirCon;
this.setTemp = setTemp;
this.isAutoDrv = isAutoDrv;
this.speed = speed;
this.color = color;
this.year = year;
this.isTurbo = false;
}
public void viewInfo() {
String airConStr = (isAirCon) ? "ON" : "OFF";
String autoStr = (isAutoDrv) ? "ON" : "OFF";
String turboStr = (isTurbo) ? "ON" : "OFF";
System.out.println("속도 : " + speed);
System.out.println("색상 : " + color);
System.out.println("제작연도 : " + year);
System.out.println("에어컨 : " + airConStr);
System.out.println("에어컨 온도 : " + setTemp);
System.out.println("자율 주행 : " + autoStr);
System.out.println("터보 모드 : " + turboStr);
}
@Override
public void airConON() {
System.out.println("에어컨을 켰습니다.");
}
@Override
public void airConOFF() {
System.out.println("에어컨을 껐습니다.");
}
@Override
public void setAitConTemp(int temp) {
System.out.println("에어컨 설정 온도를 " + temp + "로 변경 합니다.");
}
@Override
public void autoDrvON() {
System.out.println("자율 주행 모드를 켰습니다.");
}
@Override
public void autoDrvOFF() {
System.out.println("자율 주행 모드를 껐습니다.");
}
}
public class Main {
public static void main(String[] args) {
SportCar ferrari = new SportCar(false,18,
false,250, "Red", "2022");
ferrari.viewInfo();
}
}
한 클래스가 여러 클래스로 부터 상속을 받으면 여러 가지 문제가 발생 할 수 있습니다.
자바는 이런 문제를 해결하기 위해 한 클래스가 여러 인터페이스를 구현 할 수 있습니다.
public interface Buy {
void buy();
}
public interface Sell {
void sell();
}
public class Customer implements Buy, Sell {
@Override
public void buy() {
System.out.println("구매하기");
}
@Override
public void sell() {
System.out.println("판매하기");
}
}
public class CustomerTest {
public static void main(String[] args) {
Customer customer = new Customer();
Buy buyer = customer; // Customer Type의 customer 참조 변수를 Buy 인터페이스형에 대입하여 형 변환
buyer.buy(); // Buyer는 Buy 인터페이스의 메서드만 호출 가능
Sell seller = customer;
seller.sell();
Customer customer2 = (Customer) seller; // 다시 역으로 형 변환
customer2.buy();
customer2.sell();
}
}
정적 메소드는 인스턴스 생성과 상관없이 사용 할 수 있습니다.
Customer 클래스가 Buy, Sell 두 인터페이스를 구현하고 Buy 인터페이스와 Sell 인터페이스에 똑같은 디폴트 order() 메소드를 가지는 경우 문제가 됩니다.
이 경우 상속받는 Cusromer 클래스에서 재정의해서 사용해야 합니다.
public interface Buy {
void buy();
default void order() {
System.out.println("구매 주문");
}
}
public interface Sell {
void sell();
default void order() {
System.out.println("판매 주문");
}
}
public class Customer implements Buy, Sell {
@Override
public void buy() {
System.out.println("판매하기");
}
@Override
public void order() {
System.out.println("고객 판매 주문");
}
@Override
public void sell() {
System.out.println("구매하기");
}
}
public class CustomerTest {
public static void main(String[] args) {
Customer customer = new Customer();
Buy buyer = customer;
buyer.buy();
buyer.order(); // 재정의된 메소드 호출
Sell seller = customer;
seller.sell();
seller.order(); // 재정의된 메소드 호출
Customer customer1 = (Customer) seller;
customer1.buy();
customer1.sell();
customer1.order();
}
}