다형성
정의
- 클래스의 상속관계에서 오는 인스턴스의 호환성을 적극 활용할 수 있는 기능
- 수퍼클래스가 같은 인스턴스를 한 번에 관리하거나 인터페이스를 구현하여 사용하는 코드에서도 이용
종류
- up-casting
- 서브 클래스를 상위 자료형인 수퍼클래스로 변환
- down-casting
- up-casting된 인스턴스를 하위 자료형으로 변환
- up-casting과 달리 별도의 연산자가 필요
- as: 변수를 호환되는 자료형으로 변환해주는 캐스팅 연산자
- is: 변수가 자료형에 호환되는지를 먼저 ‘체크한 후 변환’해주는 캐스팅 연산자, 조건문 내에서 사용
as와 is
- as
- var a : 수퍼클래스 = 서브클래스() –> a의 자료형은 수퍼클래스이다.
- var b = a as 서브클래스 –> a는 이후로 서브클래스의 자료형으로 동작하고, as는 결과값도 반환하기 때문에 b의 변수에 저장할 수 있다.
- b도 서브클래스의 인스턴스이다.
- is
- is는 조건문 안에서만 잠시 다운캐스팅 됨.
밑의 코드는 Food인 수퍼 클래스를 Pizza 클래스가 상속받는 구조로, b는 처음에 up-casting되고, 연산자 is 혹은 as를 통해 down-casting 되며, down-casting 된 b의 결과값을 c가 받는 코드이다.
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
open class Food{
var name = "음식"
open fun eat(){
println("${name}을 먹습니다.")
}
}
class Pizza: Food(){
var type = "피자"
override fun eat(){
println("${name} 중에 ${type}을 먹습니다.")
}
fun drink(dtype: String){
println("${type}를 먹으며 ${dtype}를 마십니다.")
}
}
fun main(){
var a = Food()
a.eat()
var b: Food = Pizza() //up-casting
b.eat() // pizza 클래스의 eat 호출
// drink 함수를 호출하려면 down-casting 필요
if(b is Pizza){
b.drink("콜라")
}
var c = b as Pizza
b.drink("사이다")
c.drink("탄산수")
}
- 위 코드에서 b.eat()을 호출하면 b는 Food 자료형이지만 pizza 인스턴스이므로, pizza의 override된 eat()을 호출하여 ‘음식 중에 피자를 먹습니다.’라는 결과가 나온다.
- b는 Food 자료형이므로 Pizza의 drink 함수를 호출할 수 없다.
- is 는 조건문 내에서만 적용이 되고, b를 완전히 down-casting 하려면 as를 사용해야 한다.
- c도 b as Pizza의 결과값을 받아 Pizza의 자료형이 된다.