• 코틀린 상속 개념 총정리

    2022. 2. 27.

    by. 하루플스토리

    반응형

    안녕하세요, 하루플입니다😋

     

    이번 내용은 개발할 때 아주 많이 사용하는 내용이라 좀 더 깊게 공부하고 넘어가려 합니다.

    자바에서 상속 개념과 코틀린에서 상속 개념은 거의 동일합니다. 생성자 관계, 상속에 의한 캐스팅 부분에서 약간의 차이가 있습니다.

     

     

    상속

    상속 : 상위 클래스 멤버(함수, 프로퍼티)를 하위 클래스에서 자신의 멤버처럼 사용할 수 있게하는 기능

    상속을 쉽게 설명하기 위해 PersonInfo라는 개인정보 클래스Register라는 회원가입 클래스가 있다고 하겠습니다.

    //상위 클래스 '개인정보 클래스' 생성
    open class PersonalInfo(){
        var name: String = ""
        var age: Int = 0
    }

    상위 클래스 PersonalInfo를 다음과 같이 생성하였습니다. open 예약어를 사용하면 하위 클래스에게 상속을 허용하겠다는 뜻입니다. 아무것도 적지 않으면 상속을 허용하지 않는 final 이 자동으로 적용됩니다. 상속을 허용하기 위해 open 을 사용하였습니다.

    //회원가입 클래스 생성, PersonalInfo 클래스를 상속받음.
    class Register: PersonalInfo() {
        val personalInfo = PersonalInfo()
        personalInfo.name = "haruple"
        personalInfo.age = 26
    }

    하위 클래스인 Register 클래스 입니다.

    코드를 보니 쉽게 이해되시나요?

    상위 클래스에 선언한 멤버를 하위 클래스에서 이용할 수 있도록 해주는 것이 상속이라는 개념입니다.


    Any 클래스

    이제 좀 더 부가적인 설명을 위해 먼저 Any 클래스에 대해 알아보겠습니다.

    코틀린에서 상속을 받지 않은 클래스들은 자동으로 Any 클래스를 상속받게 됩니다.

    Any클래스는 equals()와 toString() 이외의 멤버는 제공하지 않습니다.

    class User{
        var name: String = "haruple"
        var age: Int = 26
    }

    만약 위와 같이 클래스를 선언했다고 하면

    class User: Any(){
        var name: String = "haruple"
        var age: Int = 26
    }

    위 코드처럼 Any()를 통해 상속받은 것과 동일한 코드입니다. 아무런 상속이 없으면 자동으로 Any()가 상속되기 때문이죠.


    오버라이드(Override)

    오버라이드(Override)라는 개념에 대해서도 짚고 넘어가겠습니다.

    오버라이드  : 상위 클래스에 정의된 프로퍼티나 함수를 하위 클래스에서 재정의 함.

     

    이 오버라이드 개념은 정보처리기사 시험에서도 빈출되는 만큼 객체지향 프로그래밍에서 아주 중요한 개념입니다!

    상위 클래스에 정의한 함수를 하위 클래스에서 똑같이 사용하는 것이 아니라 원하는 대로 변형해서 재정의해서 사용할 때 오버라이드를 사용합니다.

    open class A {
        open fun infoPrint(){
            println("haruple")
        }
    }
    
    class B: A(){
        override fun infoPrint(){
            println("haruple97")
        }
    }

    만약 위 코드 처럼 A 클래스의 infoPrint함수는 haruple print한다고 정의하였지만 B 클래스에서 A를 상속받아 infoPrint를 haruple97로 print 한다고 함수를 재정의 하였기 때문에 haruple97만 출력됩니다.

     

    안드로이드 개발을 해보신 분들은 Override fun onCreate() 를 많이 보셨을겁니다. 안드로이드 생명주기 중 앱이 생성될 때 실행되는 함수인데요. AppCompatActivity 클래스 내부에 onCreate() 라는 함수가 있고 이를 클래스에 재정의 해서 사용하기 때문에 앞에 Override가 붙는겁니다.

     

    ⭐️ 그리고 하위 클래스에서 Override로 정의한 함수는 상위 클래스에 자동으로 open이 적용되기 때문에 상위 클래스에서 굳이 open을 적지 않아도 상속이 가능해집니다. 만약 재정의 불가능하게 하고 싶다면 final 예약어를 직접 작성해주면 됩니다.


    상위 클래스 멤버 접근

    오버라이드를 사용하면 상위 클래스에 선언된 멤버를 하위 클래스에 재정의 해서 사용하였습니다. 그런데 상위클래스에 정의된 멤버를  재정의 하지 않고 그대로 사용하고 싶을 때도 있습니다. 이럴때 super 라는 예약어를 사용합니다.

    open class PersonalInfo(){
        open var name: String = ""
        open var age: Int = 0
        
        open fun password(){
            println("상위 클래스의 패스워드 함수")
        }
    }
    
    class Register: PersonalInfo() {
        override var name: String = "haruple"
        override var age: Int = 26
        override fun password(){
            super.password()
            println("하위 클래스에서 오버라이드한 패스워드 함수")
        }
    }

    Register 클래스의 password 클래스를 보면 super.password()를 사용하였습니다.

    상위 클래스에 정의된 멤버를 그대로 사용하기 때문에 상위 클래스에 정의한 println("상위 클래스의 패스워드 함수") 가 실행됩니다.

    그리고 재정의한 구문인 println("하위 클래스에서 오버라이드한 패스워드 함수") 가 실행됩니다.

     

    즉, 위 코드를 실행하면 아래와 같습니다.

    상위 클래스의 패스워드 함수
    하위 클래스에서 오버라이드한 패스워드 함수

    상속관계에서의 생성자

    모든 클래스에서 생성자는 최소 하나 이상 선언되어 있어야 하며 객체를 생성할 때 최소 하나 이상의 생성자가 호출되어야 합니다. 코틀린에서는 주 생성자와 보조 생성자로 구분하고 있습니다.

     

    상속 관계에서는 하위 클래스의 객체를 생성할 때 상위 클래스의 생성자는 무조건 실행되어야 합니다.

    open class User {
    
    }
    
    class Sub: User() {
    
    }
    
    val sub = Sub()

    만약 위와 같이 Sub 클래스가 User 클래스를 상속받고 맨 아래에서 Sub 객체를 생성한 경우 Sub 뿐만 아니라 User 클래스의 생성자도 함께 호출됩니다.

     

    위 코드는 아래 코드와 완전히 동일합니다.

    open class User constructor(){
    
    }
    
    class Sub constructor(): User() {
    
    }
    
    val sub = Sub()

    개발자가 첫번째 처럼 작성을 해도 컴파일러에서 자동으로 두번째 처럼 적용해줍니다.

    반응형

    댓글