자식 클래스가 여러 부모 클래스를 상속받을 수 있다면 다양한 동작을 수행할 수 있다는 장점을 가지게 될 수 있는데, 클래스를 이용하여 다중 상속을 할 경우 메서드 출처의 모호성 등 여러가지 문제가 발생할 수 있어 Java에서는 클래스를 통한 다중 상속은 지원하지 않는다.
하지만 다중 상속의 이점을 버릴 수는 없기에 Java에서는 인터페이스(Interface)라는 것을 통해 다중 상속을 지원하고 있다. JavaScript의 프로토타입(Prototype)과 비슷한 개념이다. 인터페이스는 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스를 말한다.
Java에서 추상 클래스는 추상 메서드뿐만 아니라 생성자, 필드 그리고 일반 메서드도 포함될 수 있다. 하지만 인터페이스는 오직 추상 메서드와 상수만을 가진다.
1
2
3
4
5
6
7
|
// 인터페이스(Interface)의 선언
접근제어자 interface 인터페이스명 {
public static final 타입 상수명 = 값;
...
public abstract 메서드명(매개변수1, 매개변수2 ...);
...
}
|
cs |
인터페이스의 선언은 위와 같은 방법으로 작성한다. 클래스를 작성하는 방법과 유사하다. 인터페이스를 선언할 때는 접근 제어자와 함께 interface 키워드를 사용한다. 클래스와 다른점은 인터페이스의 모든 필드는 public static final 이어야 하며, 모든 메서드는 public abstract이어야 한다.
이 부분은 모든 인터페이스에 공통적으로 적용되는 부분이기 때문에 이 제어자는 생략할 수 있다. 이렇게 생략된 제어자는 컴파일 시 Java 컴파일러가 자동으로 추가해준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
// 인터페이스(Interface)의 구현
class 클래스명 implements 인터페이스명 { ... }
interface Animal {
public abstract void cry();
}
class Cat implements Animal {
public void cry() {
System.out.println("야옹 야옹!");
}
}
class Dog implements Animal {
public void cry() {
System.out.println("멍 멍!");
}
}
public class Polymorphism {
public static void main(String[] args){
Cat cat = new Cat();
Dog dog = new Dog();
cat.cry();
dog.cry();
}
}
|
cs |
위의 코드는 인터페이스를 구현하는 과정이다. 인터페이스는 추상 클래스와 마찬가지로 자신이 직접 인스턴스를 생성할 수는 없다. 따라서 인터페이스가 포함하고 있는 추상 메서드를 구현해 줄 클래스를 작성해야만 한다.
만약 모든 추상 메서드를 구현하지 않는다면, abstract 키워드를 사용하여 추상 클래스로 선언해야 한다. 위의 코드의 결과는 야옹 야옹! 과 멍 멍!이 차례대로 출력이 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// 상속과 구현을 동시에 실행
class 클래스명 extends 상위클래스명 implements 인터페이스명 { ... }
interface Animal {
public abstract void cry();
}
interface Pet {
public abstract void play();
}
class Cat implements Animal, Pet {
public void cry(){
System.out.println("야옹 야옹!");
}
public void play(){
System.out.println("쥐 잡기 놀이하자!");
}
}
class Dog implements Animal, Pet {
public void cry(){
System.out.println("멍 멍!");
}
public void play(){
System.out.println("산책가자!");
}
}
public class Polymorphism {
public static void main(String[] args){
Cat cat = new Cat();
Dog dog = new Dog();
cat.cry();
cat.play();
dog.cry();
dog.play();
}
}
|
cs |
Java에서는 위의 코드와 같이 상속과 구현을 동시에 할 수 있다.
인터페이스는 인터페이스로부터만 상속을 받을 수 있고, 여러 인터페이스를 상속받을 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
// 클래스를 이용한 다중 상속의 문제점
class Animal {
public void cry(){
System.out.println("짖어!");
}
}
class Cat extends Animal {
public void cry(){
System.out.println("야옹 야옹!");
}
}
class Dog extends Animal {
public void cry(){
System.out.println("멍 멍!");
}
}
① class MyPet extends Cat, Dog { ... }
public class Polymorphism {
public static void main(String[] args){
MyPet pet = new MyPet();
② pet.cry();
}
}
|
cs |
위의 코드에서 Cat 클래스와 Dog 클래스는 각각 Animal 클래스를 상속받아 cry() 메서드를 오버라이딩하고 있다. 여기까지는 문제가 없지만 ①번(20행) 라인에서 MyPet 클래스가 Cat 클래스와 Dog 클래스를 동시에 상속받게 되면 문제가 발생한다. ②번(25행) 라인에서 MyPet 인스턴스인 pet이 cry() 메서드를 호출하면, 이 메서드가 Cat 클래스에서 상속받은 cry() 메서드인지 Dog 클래스에서 상속받은 cry() 메서드인지 구분할 수 없는 모호성이 생긴다. 이와 같은 이유로 자바에서는 클래스를 이용한 다중 상속을 지원하지 않는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 인터페이스의 다중상속을 통한 메서드 호출의 모호성 방지
interface Animal {
public abstract void cry();
}
interface Cat extends Animal {
public abstract void cry();
}
interface Dog extends Animal {
public abstract void cry();
}
class MyPet implements Cat, Dog {
public void cry(){
System.out.println("멍 멍! 야옹 야옹!");
}
}
public class Polymorphism {
public static void main(String[] args){
MyPet pet = new MyPet();
pet.cry();
}
}
|
cs |
하지만 위의 코드처럼 인터페이스를 이용해 다중 상속을 하게되면 이전과 같은 메서드 호출의 모호성을 방지 할 수 있다. Cat 인터페이스와 Dog 인터페이스를 동시에 구현한 MyPet 클래스에서만 cry() 메서드를 정의하고 있기 때문에 이전에 발생한 메서드 호출의 모호성이 없다.
인터페이스의 장점
인터페이스를 사용하면 다중 상속이 가능하고 아래의 장점을 더 가질 수 있다.
1. 대규모 프로젝트를 개발시 일관되고 정형화된 개발을 위한 표중화가 가능하다.
2. 클래스의 작성과 인터페이스의 구현을 동시에 진행하므로, 개발 시간을 단축할 수 있다.
3. 클래스와 클래스 간의 관계를 인터페이스로 연결해 클래스마다 독립적인 프로그래밍이 가능하다.
'프로그래밍 공부 > Java' 카테고리의 다른 글
Java - Java의 다형성 예제 (0) | 2020.02.21 |
---|---|
Java - 내부 클래스(Inner class) (0) | 2020.02.21 |
Java - 다형성(Polymorphism) (0) | 2020.02.20 |
Java - 상속(Inheritance) (0) | 2020.02.20 |
Java - 기본 생성자(Default Constructor) (1) | 2020.02.19 |