오늘은 인터페이스와 다형성에 관해 알아보자.
1. 인터페이스(Interface)란?
인터페이스는 클래스들이 공통적으로 구현해야 하는 메서드의 집합을 정의하는 추상 타입이다. 구체적인 구현을 포함하지 않고, 해당 메서드가 어떻게 동작해야 하는지에 대한 형식을 지정한다.
public interface Animal {
void sound(); // 소리를 내는 메서드
}
위의 예시에서 Animal 인터페이스는 sound() 라는 메서드를 정의하고 있다. 이 메서드는 구체적인 구현이 없고, 이를 구현하는 클래스에서 실제 동작을 정의한다.
인터페이스의 주요 목적은 다양한 클래스들이 동일한 기능을 제공할 수 있도록 표준을 제공하는 것이다. 예를 들어, 고양이와 개는 각각 다른 방식으로 소리를 내지만, Animal 인터페이스를 통해 동일한 방식으로 접근할 수 있다.
public class Dog implements Animal {
public void sound() {
System.out.println("으르르르르월월월으르르르르월월");
}
}
public class Cat implements Animal {
public void sound() {
System.out.println("냥냥냐ㅑ냐냐냥");
}
}
이렇게 인터페이스를 사용하면 서로 다른 클래스들이 동일한 메서드를 구현하도록 강제할 수 있다.
2. 다형성(Polymorphism)이란? (많을 다 , 형태 형)
조상 타입 참조 변수로 자손 타입 객체를 다루는 것.
원래 우리는 TV t = new tv(); 와 같이 타입이 같은 경우만 사용해 왔다. 하지만, 다형성의 경우 타입이 달라도 허용한다.
그렇다면 코드 예시를 통해 런타임이 시점이 어떻게 다른지 알아보자.
public class Main {
public static void main(String[] args) {
# 인터페이스 A에 구현체 B 대입
A a1 = new B();
a1.a(); # B 클래스의 a() 메서드 호출
# a1.b(); # 불가능 (A 타입 변수이므로 b()는 호출할 수 없음)
# 강제 타입 변환
System.out.println("\nB 강제 타입변환");
B b = (B) a1;
b.a(); # B 클래스의 a() 메서드 호출
b.b(); # b() 메서드도 호출 가능 (B로 변환했기 때문)
# 인터페이스 A에 구현체 C 대입
A a2 = new C();
a2.a(); # C 클래스에서 상속된 B 클래스의 a() 호출
# a2.b(); # 불가능 (A 타입이므로 b(), c() 호출 불가)
# 강제 타입 변환
System.out.println("\nC 강제 타입변환");
C c = (C) a2;
c.a(); # C는 B를 상속받았으므로 a() 호출 가능
c.b(); # C도 B를 상속받았으므로 b() 호출 가능
c.c(); # c() 호출 가능 (C 클래스의 메서드)
}
}
interface A {
void a();
}
class B implements A {
@Override
public void a() {
System.out.println("B.a()");
}
public void b() {
System.out.println("B.b()");
}
}
class C extends B {
public void c() {
System.out.println("C.c()");
}
}
이상이다.
다형성 정말 이해하기 힘든 부분이였다.
A B C 를 리모컨에 대입해서 의미를 이해하였다. 자손클래스로 내려와서 실행버튼을 눌렀을 때 그에 해당하는 항목이 작동하면 그 답을 작동하지 않으면 불가능을 정도로 이해하였다. 또한 부모 클래스에서 강제로 타입변환을 박아두면 자손클래스는 '부모의 직업이 농부라면 자손도 농부의 삶을 살아야 한다.' 라는 걸 깨달았다.