본문 바로가기

# 02/코틀린

[Kotlin] 상속과 다형성

반응형

상속과 클래스의 계층


상속(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