* Interface?
객체의 사용 방법을 정의한 타입이다. 객체의 교환성을 높여주기 때문에 다형성을 구현하는 중요한 역할을 한다. 개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출한다. 따라서 개발 코드는 객체의 내부 구조를 알 필요가 없고 인터페이스의 메소드만 알고 있으면 된다. -> 결합도 내려감
개발 코드가 직접 객체의 메소드를 호출하지 않고 중간에 인터페이스를 두는 이유는 개발 코드를 수정하지 않고, 사용하는 객체를 변경할 수 있도록 하기 위함이다. 인터페이스는 하나의 객체가 아니라 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라서 실행 내용과 리턴 값이 다를 수 있다. 따라서 개발 코드 측면에서는 코드 변경 없이 실행 내용과 리턴 값을 다양화할 수 있다는 장점을 가지게 된다.
인터페이스는 상수와 메소드만을 구성 멤버로 가진다. 인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없다. 추상 메소드와 디폴드 메소드, 정적 메소드가 선언 가능하다. 추상 메소드는 객체가 가지고 있는 메소드를 설명한 것으로 호출할 때 어떤 매개값이 필요하고, 리턴 타입이 무엇인지만 알려주고 실제 실행부는 객체(구현 객체)가 가지고 있다. 디폴트 메소드는 메소드 앞에 default가 붙는 것으로 인터페이스에 선언되지만 사실은 객체(구현 객체)가 가지고 있는 인스턴스 메소드라고 생각해야 한다.
* Interface 타입 변환과 다형성
다형성은 하나의 타입에 대입되는 객체에 따라서 실행 결과가 다양한 형태로 나오는 성질을 말한다. 인터페이스는 인터페이스 타입에 어떤 구현 객체를 대입하느냐에 따라 실행 결과가 달라진다. 상속은 같은 종류의 하위 클래스를 만드는 기술이고, 인터페이스는 사용 방법이 동일한 클래스를 만드는 기술이라는 개념적 차이점은 있지만 둘 다 다형성을 구현하는 기술이다.
- 자동 타입 변환 (Promotion)
구현 객체가 인터페이스 타입으로 변환되는 것은 자동 타입 변환(Promotion)에 해당된다. 자동 타입 변환은 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말한다.
interface 변수 = 구현 객체;
구현 객체는 인터페이스 변수로 자동 타입 변환이 일어난다.
인터페이스 구현 클래스를 상속해서 자식 클래스를 만들었다면 자식 객체 역시 인터페이스 타입으로 자동 타입 변환시킬 수 있다. 필드와 매개변수의 다형성, 인터페이스 타입으로 자동 변환된 매개값을 메소드 내에서 다시 구현 클래스 타입으로 강제 타입 변환해야 한다면 반드시 매개값이 어떤 객체인지 instanceof 연산자로 확인하고 안전하게 강제 타입 변환을 해야한다.
* Interface 상속
인터페이스도 다른 인터페이스를 상속할 수 있다. 인터페이스는 클래스와 달리 다중 상속을 지원한다.
하위 인터페이스로 타입 변환이 되면 상/하위 인터페이스에 선언된 모든 메소드를 사용할 수 있으나, 상위 인터페이스로 타입 변환되면 상위 인터페이스에 선언된 메소드만 사용 가능하고 하위 인터페이스에 선언된 메소드는 사용할 수 없다.
InterfaceC 인터페이스 변수는 methodA(), methodB(), methodC()를 모두 호출할 수 있지만, interfaceA와 interfaceB 변수는 각각 methodA()와 methodB()만 호출할 수 있다.
- 디폴드 메소드와 인터페이스 확장
디폴드 메소드는 인터페이스에 선언된 인스턴스 메소드이기 때문에 구현 객체가 있어야 사용할 수 있다. 인스턴스에서 디폴트 메소드를 허용한 이유는 기존 인터페이스를 확장해서 새로운 기능을 추가하기 위해서이다. 기존 인터페이스의 이름과 추상 메소드의 변경 없이 디폴트 메소드만 추가할 수 있기 때문에 이전에 개발한 구현 클래스를 그대로 사용할 수 있으면서 새롭게 개발하는 클래스는 디폴트 메소드를 활용할 수 있다.
- 디폴트 메소드의 필요성
기존에 MyInterface라는 인터페이스와 이를 구현한 MyClassA라는 클래스가 있었다. 이제 MyInterface에 기능을 추가해야할 필요성이 생겨 추상 메소드를 추가하였는데 MyClassA에는 추상 메소드의 실체 메소드가 없기 때문에 에러가 발생한다. 따라서 MyInterface에 디폴트 메소드를 선언하면 추상 메소드가 아니기 때문에 구현 클래스에서 실체 메소드를 작성할 필요가 없다. 따라서 MyClassA는 아무런 문제 없이 계속 사용할 수 있다.
- 디폴트 메소드가 있는 인터페이스 상속
부모 인터페이스에 디폴트 메소드가 정의되어 있을 경우 자식 인터페이스에서 디폴트 메소드를 활용하는 방법은
- 디폴트 메소드를 단순히 상속만 받는다.
- 디폴트 메소드를 재정의(Override)해서 실행 내용을 변경한다.
- 디폴트 메소드를 추상 메소드로 재선언한다.
'JAVA' 카테고리의 다른 글
Map Collection (0) | 2021.07.08 |
---|---|
Collection Framework (0) | 2021.07.05 |
String과 StringBuilder 비교하기 (String vs StringBuilder) (0) | 2021.06.21 |
메모리 구조(Stack, Heap) (0) | 2021.06.20 |
JDBC: executeQuery VS excuteUpdate (0) | 2021.04.25 |