인터페이스
인터페이스는 class 가 아닌 interface 키워드를 사용한다. public abstract 키워드는 생략 가능하다.
- 인터페이스의 메서드는 모두 public, abstract 이다.
- 메서드에 public abstact를 생략할 수 있다.
- 다중 상속을 지원한다.
인터페이스와 멤버 변수
인터페이스에서 멤버 변수는 public, static, final 이 모두 포함되었다고 간주된다.
인터페이스를 통해서 상수에 접근할 수 있다고 보면된다.
예제
InterfaceAnimal.java
package poly.ex4;
public interface interfaceAnimal {
void sound(); //public abstact
void move();
}
Cat.java
public class Cat implements interfaceAnimal{
@Override
public void sound() {
System.out.println("냐옹");
}
@Override
public void move() {
System.out.println("냥이 이동");
}
}
Dog.java
public class Dog implements interfaceAnimal {
@Override
public void sound() {
System.out.println("멍멍");
}
@Override
public void move() {
System.out.println("댕댕이 이동");
}
}
Caw.java
public class Caw implements interfaceAnimal{
@Override
public void sound() {
System.out.println("음메");
}
@Override
public void move() {
System.out.println("집으로 이동");
}
}
InterfaceMain.java
public class InterfaceMain {
public static void main(String[] args) {
Dog dog = new Dog();
Caw caw = new Caw();
Cat cat = new Cat();
soundAnimal(dog);
soundAnimal(cat);
soundAnimal(caw);
}
public static void soundAnimal(interfaceAnimal animal) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
실행결과
인터페이스를 사용하는 이유
모든 메서드가 추상 메서드인 경우 추상 클래스를 만들어도 되고, 인터페이스를 만들어도 된다. 그런데 왜 인터페이스를 사용해야 할까?
- 제약: 인터페이스를 만드는 이유는 인터페이스를 구현하는 곳에서 인터페이스의 메서드를 반드시 구현하라는 제약을 주기 위해서이다. 추상클래스의 경우 누군가 실행 가능한 메서드를 끼워 넣을 수도 있다. 이 경우 추가된 기능을 자식 클래스에서 구현하지 않을 수도 있다. 인터페이스를 만들면 이 문제를 원천 차단할 수 있다.
- 다중 구현 : 자바에서 클래스 상속은 부모를 하나만 지정할 수 있다. 반면에 인터페이스는 부모를 여러명 두는 다중 구현이 가능하다.
인터페이스 다중구현
자바는 클래스의 다중 상속을 지원하지 않는다. 만약 AirplandCar가 Airplane과 Car를 상속받는다고 가정해보자. AirplaneCar에서 move() 메서드를 호출할 때 어떤 부모의 move()를 호출할 지 애매한 문제가 발생한다. 이를 다이아몬드 문제라고 한다. 또한 다중 상속을 사용하면 클래스 계층 구조가 매우 복잡해질 수 있다. 이런 문제점 때문에 자바는 클래스의 다중 상속을 허용하지 않는다. 대신 인터페이스의 다중 구현을 허용하여 이러한 문제를 피한다.
예제
InterfaceA.java
package poly.diamond;
public interface InterfaceA {
void methodA();
void methodCommon();
}
InterfaceB.java
package poly.diamond;
public interface InterfaceB {
void methodB();
void methodCommon();
}
Child.java
package poly.diamond;
public class Child implements InterfaceA, InterfaceB{
@Override
public void methodA() {
System.out.println("Child methodA");
}
@Override
public void methodB() {
System.out.println("Child methodB");
}
@Override
public void methodCommon() {
System.out.println("Child methodCommon");
}
}
DiamondMain.java
package poly.diamond;
public class DiamondMain {
public static void main(String[] args) {
InterfaceA a = new Child();
a.methodA();
a.methodCommon();
InterfaceB b = new Child();
b.methodB();
b.methodCommon();
}
}
실행결과
=>
1. a.methodCommon()을 호출하면 먼저 x001 Child 인스턴스를 찾는다.
2. 변수 a가 InterfaceA 타입이므로 해당 타입에서 methodCommon()을 찾는다.
3. methodCommon()은 하위 타입인 Child에서 오버라이딩 되어 있다. 따라서 Child의 methodCommon()이 호출된다.
* 인프런 '김영한의 실전 자바 - 기본편'을 참고하여 작성하였습니다.
'프로그래밍언어 > Java' 카테고리의 다른 글
[Java 기본] OCP(Open-Closed Principle) 원칙 (0) | 2024.07.26 |
---|---|
[Java 기본] 좋은 객체 지향 프로그래밍이란? (0) | 2024.07.26 |
[Java 기본] 추상 클래스 (0) | 2024.07.25 |
[Java 기본] 다형성 활용 (0) | 2024.07.25 |
[Java 기본] 다형성과 메서드 오버라이딩 (0) | 2024.07.23 |