인터페이스란?
자바에서는 클래스를 통한 다중 상속은 지원하지 않지만 인터페이스를 통해 다중 상속을 지원한다.
인터페이스는 일종의 추상클래스로 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화의 정도가 더 높아 추상메서드와 상수
만을 가질 수 있다.
인터페이스를 정의하는 방법
- 클래스의 작성하는 방법과 같으며 class대신
interface
를 사용한다. - 클래스와 달리 모든 멤버는
public static final
이어야 한다. - 모든 메서드는
public abstract
이어야 하며 생략 가능하다.- 단 static메서드와 default메서드는 예외이다(JDK 1.8부터)
interface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름(매개변수);
}
인터페이스를 구현하는 방법
인터페이스도 추상클래스 처럼 자신이 직접 인스턴스를 생성할 수 없으며 구현해줄 클래스를 만들어야 한다. 이때 추상메서드와는 다르게 implements
키워드를 사용하며 모든 추상메서드를 구현하지 않으면 abstact를 붙여 추상클래스로 선언해야 한다.
class 클래스명 implements 인터페이스명{}
public interface Car {
public abstract void printFuel();
public abstract String getFuel();
}
public class ElectricCar implements Car {
@Override
public void printFuel() {
System.out.println("이 차의 연료는 전기");
}
@Override
public String getFuel() {
return "전기";
}
}
public abstract class GasCar implements Car{
@Override
public void printFuel() {
System.out.println("이 차의 연료는 가스");
}
}
인터페이스를 레퍼런스를 통해 구현체를 사용하는 방법
자식 클래스의 인스턴스를 부모 클래스의 타입의 참조변수로 참조하는 것이 가능하였는데(다형성) 인터페이스 또한 가능하다.
public class CarManager {
public static Car getCar(String fuel) {
if (fuel.equals("기름"))
return new OilCar();
else if (fuel.equals("전기"))
return new ElectricCar();
else
return new OtherCar();
}
}
Car car1 = CarManager.getCar("전기"); // Car car1 = new ElectricCar();
Car car2 = CarManager.getCar("기름");
Car car3 = CarManager.getCar("고급 휘발유");
car1.printFuel();
car2.printFuel();
car3.printFuel();
출력 결과
이 차의 연료는 전기
이 차의 연료는 기름
이 차의 연료는 분류되지 않음
인터페이스 상속
인터페이스는 다른 인터페이스로부터만 상속할 수 있으며 클래스와 다르게 여러 인터페이스를 상속할 수 있다.
클래스의 상속과 마찬가지로 자식은 부모에 정의된 모든 멤버를 상속받는다.
public class ElectricCar implements Car, Vehicle {
@Override
public void printFuel() {
System.out.println("이 차의 연료는 전기");
}
@Override
public String getFuel() {
return "전기";
}
}
인터페이스의 기본 메소드
Java8부터 기본 구현을 제공하는 메소드로 디폴트 메소드는 추상 메소드가 아니므로 추가되어도 인터페이스를 구현한 클래스를 변경하지 않아도 된다.
메소드 앞에 default
키워드를 붙이고 추상메서드와 다르게 몸통{}이 있어야 한다.
접근제어자는 public이며 생략 가능하다.
public interface Car {
public abstract void printFuel();
public abstract String getFuel();
default void newMethod(){}
}
새로 추가한 메소드가 기존의 메소드와 이름이 같아 충돌하는 경우가 발생할 수 있다.
- 여러 인터페이스의 기본 메소드간 충돌
- 인터페이스를 구현한 클래스에서 기본 메소드를 오버라이딩
- 기본 메서드와 부모클래스의 메소드간 충돌
- 부모 클래스의 메소드가 상속되고 기본 메소드 무시
인터페이스의 static 메소드
static 메소드 역시 Java8부터 추가되었으며 접근 제어자는 public으로 생략 가능합니다.
static을 붙여 오버라이딩이 불가능하며 인스턴스를 생성하여 호출을 할 수 없고 클래스명.메소드명();
으로 호출해야 한다.
인터페이스의 private 메소드
Java9에 대한 학습을 따로 하지 않아서 알지 못했던 부분인데 Java9부터 인터페이스에 private메소드와 private static 메소드를 사용할 수 있게 되었다.
인터페이스를 구현하는 클래스에 재정의하거나 사용할 수 없으며 default나 static 메소드를 통해서만 사용할 수 있다.
public interface Car {
public abstract void printFuel();
public abstract String getFuel();
default void newMethod(){
staticMethod();
}
private static void staticMethod(){
System.out.println("static!");
}
}
참고 문서
Java의 정석 - 남궁 성
http://www.tcpschool.com/java/intro
https://velog.io/@foeverna/Java-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%9D%98-%EC%9A%94%EC%86%8C%EB%93%A4