인터페이스란?
인터페이스는 일종의 추상클래스(abstract class)이다.
추상클래스(abstract class)는 일반 메서드도 포함할 수 있지만 인터페이스는 오직 추상메서드와 상수만을 멤버로 가실 수 있다.
추상클래스(abstract class)는 부분적으로 완성된 미완성 설계도라고 한다면, 인터페이스는 밑그림만 그려져 있는 기본 설계도라고 생각하면 된다.
인터페이스 자체만으로 사용되기 보다는 다른 클래스를 작성하는데 도움을 줄 목적으로 작성된다.
인터페이스 제약사항
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
- 모든 메서드는 public abstract 이어야 하며, 이를 생략 할 수 있다. 단, static 메서드와 디폴트 메서드는 예외 (JDK1.8부터 변경)
인터페이스의 작성
인터페이스는 class 대신 interface를 사용해 작성한다.
interface CarInterface { // 인터페이스
public abstract void powerOnOff();
void gearShifting(); // public abstract 생략
}
인터페이스의 상속
인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 달리 다중상속이 가능하다.
interface CarPowerInterface {
void powerOnOff();
}
interface CarGearInterface {
void gearShifting();
}
interface CarInterface extends CarPowerInterface, CarGearInterface { }
인터페이스의 구현
인터페이스는 추상클래스(abstract class) 처럼 그 자체로는 인스턴스를 생성할 수 없다.
인터페이스도 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 한다.
implements 키워드를 사용한다.
만일 구현하는 인터페이스의 메서드 중 일부만 구현한다면 인터페이스 대신 추상클래스(abstract class)로 선언해야 한다.
한 클래스에 추상클래스(abstract class)를 상속받고 인터페이스 구현을 동시에 할 수 있다.
interface CarInterface {
...
}
abstract class CarAbstract {
...
}
class Car extends CarAbstract implements CarInterface {
...
}
인터페이스를 이용한 다형성
인터페이스를 구현하게 되면 해당 인터페이스가 조상이라 할 수 있으므로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로의 형변환도 가능하다.
CarInterface carInterface = new Car();
리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
public CarInterface method() {
Car car = new Car();
return car;
}
인터페이스의 장점
- 개발시간을 단축 시킬 수 있다.
인터페이스가 작성되면 어떠한 메서드들이 있는지 확인 가능 하기 때문에 동시에 상속받고 개발이 가능하다. - 포준화가 가능하다.
프로젝트에 기본적인 틀을 인터페이스로 작성한 다음, 개발자들에게 인터페이스를 구현하여 프로그램을 작성하도록 함으로써 보다 일관되고 정형화된 프로그램의 개발이 가능하다. - 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
서로 상속관계에 있지도 않고, 같은 조상클래스를 가지고 있지 않은 아무런 관계도 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현함으로써 관계를 맺어줄 수 있다. - 독립적인 프로그래밍이 가능하다.
클래스와 클래스간의 직접적인 관계를 인터페이스를 이용해서 간접적인 관계로 변경하면, 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능하다.
인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제 구현에 독립적인 프로그램을 작성하는 것이 가능하다.
인터페이스의 이해
- 클래스를 사용하는 쪽(User)과 클래스를 제공하는쪽(Provider)이 있다.
- 메서드를 사용(호출)하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면 된다.
클래스 간 직접적인 연관이 있는 경우
class A {
public void play(B b) {
b.play();
}
}
class B {
public void play() {
System.out.println("B class -> play");
}
}
class C {
public void play() {
System.out.println("C class -> play");
}
}
A a = new A();
a.play(new B()); // 클래스 B와 직접적인 연관(의존성)이 있다.
a.play(new C()); // 오류발생, 매개변수의 타입이 맞지 않다.
/*
* - 클래스 B가 변경되면 A 클래스에 play 메서드도 변경될 가능성이 크다.
* - 매개변수로 B 클래스만 선언했기 때문에 다른 클래스는 매개변수로 사용할 수 없다.
*/
인터페이스를 이용해 간접적인 연관이 있는 경우
interface I {
public abstract void play();
}
class InstanceManager {
public static I getInstance() {
return new B();
// return new C();
}
}
class A {
// 매개변수로 I인터페이스를 제공받는다.
public void play(I i) {
i.play();
}
// 매개변수로 I인터페이스를 제공받지 않고
// 제 3의 클래스의 메서드를 통해서 I인터페이스를 구현한 클래스를 얻어올 수 있다.
public void play2() {
I i = InstanceManager.getInstance();
i.pay();
}
}
class B implements I {
public void play() { // overriding
System.out.println("B class -> play");
}
}
class C implements I {
public void play() { // overriding
System.out.println("C class -> play");
}
}
A a = new A();
a.play(new B()); // B클래스와 연관(의존성)이 없고 I인터페이스와의 연관이 있다.(간접적)
a.play(new C()); // C클래스도 I인터페이스를 구현하므로 매개변수로 사용할 수 있다.
a.play2();
디폴트 메서드와 static 메서드
원래는 인터페이스에 추상 메서드만 선언할 수 있었는데, JDK1.8부터 디폴트 메서드와 static메서드도 추가할 수 있다.
인터페이스의 static메서드 역시 접근 제어자(access modifier)가 항상 public이며, 생략할 수 있다.
디폴트 메서드
인터페이스에 추상메서드를 추가 할 경우 해당 인터페이스를 구현한 클래스에 모두 오버라이딩(overriding)을 해야하는 엄청난 작업이 생긴다.
이를 해결하기 위해 디폴트 메서드(default method)라는 것을 고안해 내었다.
디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드로, 추상 메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.
디폴트 메서드 역시 접근 제어자(access modifier)가 public 이며 생략가능하다.
interface I {
void methodA();
default void methodB() {
...
}
}
디폴트 메서드를 사용할 때는 기존 메서드와 이름이 중복되어 충돌하는 경우가 발생한다.
- 여러 인터페이스의 디폴트 메서드 간의 충돌
디폴트 메서드가 필요한 쪽의 클래스만 오버라이딩(overriding)해서 해결하기도 한다.
인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩(overriding) 해야 한다. - 디폴드 메서드와 조상 클래스의 메서드간의 충돌
조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.
'Java' 카테고리의 다른 글
예외처리(Exception handling) (0) | 2021.09.20 |
---|---|
내부 클래스(Inner class) (0) | 2021.09.20 |
추상클래스(Abstract class) (0) | 2021.09.19 |
다형성(polymorphism) (0) | 2021.09.16 |
그 외 제어자(otherwise modifier) (0) | 2021.09.16 |