본문 바로가기
2학년 2학기/모바일 소프트웨어 - 코틀린

Class(1) - 상속

by print_soo 2024. 10. 1.

상속 (Inheritance)

상속에는 클래스 상속과 인터페이스 상속이 있는데 우선 클래스 상속에 대해서만 알아보자.

 

클래스 상속은 단일 상속이므로 한 부모에게만 상속 받을 수 있다.

 

부모클래스 명칭

  • super class
  • base class
  • parent class

 

자식 클래스 명칭

  • sub class 
  • derived class
  • child calss

 

 부모 클래스를 선언하고 자식 클래스에 상속 하는 과정

: 상속이 가능하게 하려면 부모 클래스가 될 클래스 앞에 open이라는 키워드를 작성해주어야한다.

 

 

 

[상속하기 전 3개의 클래스 선언]

 

class Animal {
    var color: String = ""
    fun eat(){
        println("냠냠")
    }
}

class Dog {
    var color: String = ""
    var breed: String = ""
    fun bark(){
        println("멍멍")
    }
    fun eat(){
        println("냠냠")
    }
}

class Cat {
    var color: String = ""
    var age: Int = 0
    fun meow(){
        println("냐옹")
    }
    fun eat(){
        println("냠냠")
    }
}

 


 

[상속이 가능하도록 open 키워드 설정]

 

//open 키워드는 본인을 상속해도 된다는 의미
open class Animal {
    var color: String = ""
    fun eat(){
        println("냠냠")
    }
}

class Dog {
    var color: String = ""
    var breed: String = ""
    fun bark(){
        println("멍멍")
    }
    fun eat(){
        println("냠냠")
    }
}

class Cat {
    var color: String = ""
    var age: Int = 0
    fun meow(){
        println("냐옹")
    }
    fun eat(){
        println("냠냠")
    }
}

 


 

[Animal 클래스를 Dog과 Cat 클래스에 상속]

 

//open 키워드는 본인을 상속해도 된다는 의미
open class Animal {
    var color: String = ""
    fun eat(){
        println("냠냠")
    }
}

class Dog: Animal() {
    var breed: String = ""
    fun bark(){
        println("멍멍")
    }
}

class Cat: Animal() {
    var age: Int = 0
    fun meow(){
        println("냐옹")
    }
}

 

 

 

 

이렇게 상속을 받으면 이미 부모클래스에 있는 프로퍼티나 메소드는 다시 정의하지 않아도 사용할 수 있다.

 

fun main() {
    var dog = Dog()
    dog.breed = "dachshund" 
    dog.color = "brown" //상속 받음
    dog.bark()
    dog.eat() //상속 받음
}


//[with 사용해서 생략 가능]
//fun main() {
//    var dog = Dog()
//    with(dog){
//        breed = "dachshund"
//        color = "brown" //상속 받음
//        bark()
//        eat() //상속 받음
//    }
}

 

 

 

재정의

: 부모 클래스의 특정 프로퍼티나 메서드를 재정의하기 위해서는 해당 프로퍼티나 메서드 앞에 open이라는 키워드를 작성해주어야한다.

또한 자식 클래스는 재정의할 메소드를 작성할 때 override 라는 키워드를 작성해주어야 한다.

 

//open 키워드는 본인을 상속해도 된다는 의미
open class Animal {
    open var color: String = "white"
    open fun eat(){
        println("냠냠")
    }
}

class Dog: Animal() {
    override var color: String = "black"
    var breed: String = ""
    fun bark(){
        println("멍멍")
    }
    override fun eat(){
        println("Dog eat")
    }

}

class Cat: Animal() {
    override var color: String = "green"
    var age: Int = 0
    fun meow(){
        println("냐옹")
    }
    override fun eat(){
        println("Cat eat")
    }
}



fun main() {
    var dog = Dog()
    with(dog){
        print(dog.color) // black
        eat()  // Dog eat
    }
}

 

 


 

기본 생성자(주 생성자)를 이용한 초기화를 진행했을 때 자식 클래스는 어떻게 해야할까?

 

 

부모 클래스에는 A, B 프로퍼티가 있고 자식 클래스에는 C 프로퍼티가 있다고 생각해보자.

 

부모 클래스와 자식 클래스가 주 생성자를 이용해서 프로퍼티 값을 초기화 시켰을다고 생각해보면 부모 클래스는 A, B만 초기화 하면 되지만 자식 클래스는 A, B가 상속 되었기 때문에 A, B, C를 모두 초기화 해주어야한다. 

이런 상황이 벌어졌을 때 자식 클래스에서는 부모 클래스에서 상속 받은 프로퍼티를 어떻게 처리 해주어야할까?

 

 

자식 클래스에서 부모 클래스의 생성자를 사용한다는 표시를 해주면 된다. 

 

open class Animal (var color: String, var age: Int) {
   init{
       println("Animal class의 색상: $color, 나이: $age")
   }
}

class Dog(color: String, age: Int, breed: String): Animal(color, age) { //부모 클래스의 생성자를 사용한다는 의미
    init{
        println("Dog class의 색상: $color, 나이: $age, 품종: $breed")
    }
}

fun main() {
   var dog = Dog("green", 12, "bulldog")
}

//출력
//Animal class의 색상: green, 나이: 12
//Dog class의 색상: green, 나이: 12, 품종: bulldog

 

핵심은 자식 클래스가 부모 클래스의 프로퍼티를 초기화할 때는 부모 생성자를 호출해서 super처럼 기본 생성자를 사용하고, 추가로 자식 클래스의 고유한 프로퍼티도 초기화한다.

 

 

그렇다면, 보조 생성자를 사용한 경우에는??

super 키워드를 사용해주면 된다!

 

//open 키워드는 본인을 상속해도 된다는 의미
open class Animal {
    var color: String
    var age: Int
    constructor(color: String, age: Int) {
        this.color = color
        this.age = age
    }
}

class Dog: Animal {
    var breed: String
    constructor(color: String, age: Int, breed: String) : super(color, age) {
        this.breed = breed
    }
}

fun main() {
   var dog = Dog("green", 12, "bulldog")
}

 

 

핵심은 보조 생성자를 사용할 때는 부모 클래스의 생성자를 호출하기 위해 super 키워드를 명시적으로 사용해야 한다. 이를 통해 부모 클래스의 프로퍼티를 초기화한 후, 자식 클래스 고유의 프로퍼티도 초기화한다