상속과 클래스의 계층
상속(inheritance)
- 자식 클래스를 만들 때 상위 클래스(부모 클래스)의 속성과 기능을 물려받아 계승
- 상위(부모) 클래스의 프로퍼티와 메서드가 자식에 적용됨
Any - 상위 클래스(super class)
open 클래스(상속 가능) - Bird - 기반 클래스(parent class or base class)
상속(Inheritance)
기본클래스(최종 클래스, 상속불가) - Lark, Parrot - 파생 클래스(child class or derived class)
상속 가능한 클래스와 하위 클래스 선언
- open 키워드를 통한 선언
open class 기반 클래스명 { // open으로 파생 가능 (다른 클래스가 상속 가능한 상태가 됨)
...
}
class 파생 클래스명 : 기반 클래스명() { // 기반 클래스로부터 상속, 최종 클래스로 파생 불가
...
}
- 코틀린의 모든 클래스는 묵시적으로 Any로부터 상속
BirdChildClasses.kt
// 1. 상속 가능한 클래스를 위해 open 사용
open class Bird ( var name : String, var wing : Int, var beak : String, var color : String ) {
// 메서드
fun fly() = println ( "Fly wing : $wing" )
fun sing ( vol : Int ) = println ( "Sing vol : $vol" )
}
// 2. 주 생성자를 사용하는 상속
class Lark ( name : String, wing : Int, beak : String, color : String ) : Bird ( name, wing, beak, color ) {
fun singHitone() = println ( "Happy Song!" ) // 새로 추가된 메서드
}
// 3. 부 생성자를 사용하는 상속
class Parrot : Bird {
val language : String
constructor ( name : String, wing : Int, beak : String, color : String , language : String) : super ( name, wing, beak, color ) {
this. language = language // 새로 추가된 프로퍼티
}
fun speak() = println ( "Speak! $language" )
}
fun main() {
val coco = Bird( "mybird", 2, "short", "blue" )
val lark = Lark( "mylark", 2, "long", "brown" )
val parrot = Parrot( "myparrot", 2, "short", "multiple", "korean") // 프로퍼티가 추가됨
println( "Coco : ${coco.name}, ${coco.wing}, ${coco.beak}, ${coco.color}" )
println( "Lark : ${lark.name}, ${lark.wing}, ${lark.beak}, ${lark.color}" )
println( "Parrot : ${parrot.name}, ${parrot.wing}, ${parrot.beak}, ${parrot.color}, ${parrot.language}" )
lark.singHitone() // 새로 추가된 메서드가 사용 가능
parrot.speak()
lark.fly()
}
- 하위 클래스는 상위 클래스의 메서드나 프로퍼티를 그대로 상속하면서 상위 클래스에는 없는 자신만의 프로퍼티나 메서드를 확장
다형성(polymorphism)
- 같은 이름을 사용하지만 구현 내용이 다르거나 매개변수가 달라서 하나의 이름으로 다양한 기능을 수행할 수 있는 개념
오버라이딩(overriding)
- 기능을 완전히 다르게 바꾸어 재설계
- 누르다 -> 행위 -> push()
- push()는 '확인' 혹은 '취소' 용도로 서로 다른 기능을 수행 할 수 있음
오버로딩(overloading)
- 기능은 같지만 인자를 다르게 하여 여러 경우를 처리
- 출력한다 -> 행위 -> print()
- print(123), print("Hello") 인자는 다르지만 출력의 기능은 동일함
일반 함수에서의 오버로딩
fun add ( x : Int, y : Int ) : Int { // 정수 자료형 매개변수 2개를 더함
return x + y
}
fun add ( x : Double, y : Double ) : Double { // 실수 자료형 매개변수 2개를 더함
return x + y
}
fun add ( x : Int, y : Int, z : Int ) : Int { // 정수 자료형 매개변수 3개를 더함
return x + y + z
}
클래스 메서드의 오버로딩
OverloadCalc.kt
fun main() {
val calc = Calc()
println ( calc.add( 3, 2 ) )
println ( calc.add( 3.2, 1.3 ) )
println ( calc.add( 3, 3, 2 ) )
println ( calc.add( "Hello", "World" ) )
}
class Calc {
// 다양한 매개변수로 오버로딩된 메서드들
fun add ( x : Int, y : Int ) : Int = x + y
fun add ( x : Double, y : Double ) : Double = x + y
fun add ( x : Int, y : Int, z : Int ) : Int = x + y + z
fun add ( x : String, y : String) : String = x + y
}
오버라이딩
- 오버라이드(override)란 사전적 의미로 '(기존의 작업을) 중단하다', '뒤엎다' 등으로 해석
- 상위 클래스의 메서드의 내용을 완전히 새로 만들어 다른 기능을 하도록 정의
- 오버라이딩하기 위해 부모 클래스에서는 open 키워드, 자식 클래스에서는 override 키워드를 각각 이용
- 메서드 및 프로퍼티등에 사용할 수 있다.
메서드 오버라이딩의 예
open class Bird { // 여기의 open은 상속 가능을 나타냄
...
fun fly() { ... } // 1. 최종 메서드로 오버라이딩 불가
open fun sing() { ... } // 2. sing() 메서드는 하위 클래스에서 오버라이딩 가능
}
class Lark() : Bird() { // 3. 하위 클래스
fun fly() { /* 재정의 */ } // 에러! 상위 메서드에 open 키워드가 없어 오버라이딩 불가
override fun sing() { /* 구현부를 새롭게 재정의 */ } // 4. 구현부를 새롭게 작성
}
오버라이딩 금지
- 파생 클래스에서 오버라이딩을 금지할 때
open class Lark() : Bird() {
final override fun sing() { /* 구현부를 새롭게 재정의 */ } // 하위 클래스에서 재정의 금지
}
BirdOverrideEx.kt
// 상속 가능한 클래스를 위해 open 사용
open class Bird ( var name : String, var wing : Int, var beak : String, var color : String ) {
// 메서드
fun fly() = println( "Fly wing : $wing" )
open fun sing ( vol : Int ) = println ( "Sing vol : $vol" ) // 오버라이딩 가능한 메서드
}
class Parrot ( name : String,
wing : Int = 2,
beak : String,
color : String, // 마지막 인자만 var로 선언되어 프로퍼티가 추가됨
var language : String = "natural" ) : Bird ( name, wing, beak, color ) {
fun speak() = println ( "Speak! $language" ) // Parrot에 추가된 메서드
override fun sing ( vol : Int ) { // 오버라이딩된 메서드
println ( "I'm a parrot! The volume level is $vol" )
speak() // 달라진 내용!
}
}
fun main() {
val parrot = Parrot ( name = "myparrot", beak = "short", color = "multiple" )
parrot.language = "English"
println ( "Parrot : ${parrot.name}, ${parrot.wing}, ${parrot.beak}, ${parrot.color}, ${parrot.language}" )
parrot.sing(5) // 달라진 메서드 실행 가능
}
'# 02 > 코틀린' 카테고리의 다른 글
[Kotlin] 언어의 특징 (0) | 2019.08.12 |
---|---|
[Kotlin] super와 this의 참조 (0) | 2019.08.08 |
[Kotlin] 생성자 (0) | 2019.08.06 |
[Kotlin] 클래스와 객체의 정의 (0) | 2019.08.06 |
[Kotlin] 흐름의 중단과 반환 (0) | 2019.08.06 |