다형성
- 하나의 객체가 여러개의 자료형 타입을 가질 수 있는 것
인터페이스에서 사용한 코드에 추가로 ‘경비원’ 클래스를 형성,
경비원 클래스는 동물을 짖게(barkAnimal) 하여 건물을 지킨다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Bouncer {
void barkAnimal(Animal animal) {
if (animal instanceof Tiger) {
System.out.println("어흥");
} else if (animal instanceof Lion) {
System.out.println("으르렁");
}
}
}
public class Sample {
public static void main(String[] args) {
Tiger tiger = new Tiger();
Lion lion = neaw Lion();
Bouncer bouncer= new Bouncer();
bouncer.barkAnimal(tiger); // 어흥
bouncer.barkAnimal(lion); // 으르렁
}
}
- instanceof: 어떤 객체가 특정 클래스의 객체인지를 조사할 때 사용되는 자바의 내장 명령어
- animal instanceof Tiger 는 “animal 객체는 Tiger 클래스로 만들어진 객체인가?”를 묻는 조건문
- IS-A 관계에서 배웠듯, tiger과 lion은 animal 객체로 볼 수 있다.
위 코드를 interface를 이용하여 개선
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
interface Barkable {
void bark();
}
class Tiger extends Animal implements Predator, Barkable {
public String getFood() {
return "apple";
}
public void bark() {
System.out.println("어흥");
}
}
class Lion extends Animal implements Predator, Barkable {
public String getFood() {
return "banana";
}
public void bark() {
System.out.println("으르렁");
}
}
class Bouncer {
void barkAnimal(Barkable animal) { // Animal 대신 Barkable을 사용
animal.bark();
}
}
- 위 코드의 tiger, lion 객체는 각각 Tiger, Lion 클래스의 객체이면서, Animal 클래스의 객체이기도 하고, Barkable, Predator 인터페이스의 객체이기도 하다.
- 이러한 이유로 barkAnimal 메소드의 입력 자료형을 Animal에서 Barkable 로 바꾸어 사용할 수 있는 것
Tiger 클래스의 객체는 아래와 같이 여러가지 자료형으로 표현 가능
1
2
3
4
Tiger tiger = new Tiger(); // Tiger is a Tiger
Animal animal = new Tiger(); // Tiger is a Animal
Predator predator = new Tiger(); // Tiger is a Predator
Barkable barkable = new Tiger(); // Tiger is a Barkable
주의사항
- Predator 로 선언된 predator 객체와 Barkable 로 선언된 barkable 객체는 사용할 수 있는 메소드가 서로 다르다.
- predator 객체는 getFood() 메소드만 사용가능
- barkable 객체는 bark() 메소드만 호출이 가능
- getFood 메소드와 bark 메소드를 모두 사용하고 싶다면?
- Predator, Barkable 인터페이스를 구현한 Tiger 로 선언된 tiger 객체를 그대로 사용 (여러개의 인터페이스(Predator, Barkable)를 동시에 상속가능)
※ 일반 클래스는 단일상속만 가능 - getFood, bark 메소드를 모두 포함하는 새로운 인터페이스를 새로 만들어 사용
- Predator, Barkable 인터페이스를 구현한 Tiger 로 선언된 tiger 객체를 그대로 사용 (여러개의 인터페이스(Predator, Barkable)를 동시에 상속가능)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface Barkable {
void bark();
}
interface BarkablePredator extends Predator, Barkable {
}
class Lion extends Animal implements BarkablePredator {
public String getFood() {
return "banana";
}
public void bark() {
System.out.println("으르렁");
}
}
전체 소스코드
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
interface Predator {
String getFood();
default void printFood() {
System.out.printf("my food is %s\n", getFood());
}
int LEG_COUNT = 4; // 인터페이스 상수
static int speed() {
return LEG_COUNT * 30;
}
}
interface Barkable {
void bark();
}
interface BarkablePredator extends Predator, Barkable {
}
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Tiger extends Animal implements Predator, Barkable {
public String getFood() {
return "apple";
}
public void bark() {
System.out.println("어흥");
}
}
class Lion extends Animal implements BarkablePredator {
public String getFood() {
return "banana";
}
public void bark() {
System.out.println("으르렁");
}
}
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed " + predator.getFood());
}
}
class Bouncer {
void barkAnimal(Barkable animal) {
animal.bark();
}
}
public class Sample {
public static void main(String[] args) {
Tiger tiger = new Tiger();
Lion lion = new Lion();
Bouncer bouncer = new Bouncer();
bouncer.barkAnimal(tiger);
bouncer.barkAnimal(lion);
}
}
참고자료
점프 투 자바 - 객체지향 프로그래밍