06_상속과 인터페이스

소정·2024년 7월 11일
0

Android_with_compose

목록 보기
6/17

상속이란

상속은 한 클래스가 다른 클래스의 속성과 매소드를 물려받는 것
코드 재사용과 확장에 용이하다.

코틀린에서 상속을 사용하기 위해선 부모가 될 클래스에 open 키워드를 붙여줘야함

오버로딩 vs 오버라이딩
오버로딩 : 매소드의 이름은 같지만 매개변수의 타입이나 갯수가 다른것
오버라이딩 : 자식 클래스에서 상속받은 부모의 매소드를 재정의 하는것

예시

fun main() {

        val obj1 = BaseClass()
        obj1.coreValue()

        val obj2 = Secondary()
        obj2.coreValue()


    }
    
    
    open class BaseClass {
    //다른 class들이 상속 받을 클래스
    //open 키워드를 써서 class를 상속 할 수 있는 상태로 만든다
    fun coreValue() {
        println("베이스 클래스")
    }
}

class Secondary : BaseClass() {
}
   

Secondary class엔 아무것도 없지만 BaseClass()를 상속받았기때문에 coreValue() 함수 호출 가능

오버라이딩과 super

오버라이딩 : 상속 관계에서 부모의 함수를 자식 클래스에서 재정의
-> 코틀린에서 함수를 오버라이딩 할 수있도록 하려면 함수에도 open키워드를 써줘야 한다

super : 오버라이딩한 함수를 실행할 때 부모에서 정의한 내용을 먼저 실행하란뜻

fun main() {

    val obj1 = BaseClass()
    obj1.coreValue()

    val obj2 = Secondary()
    obj2.coreValue()
    obj2.role()

}

open class BaseClass {
    //다른 class들이 상속 받을 클래스
    //open 키워드를 써서 class를 상속 할 수 있는 상태로 만든다
    fun coreValue() {
        println("베이스 클래스")
    }
    
    open fun role() { //오버라이딩 할 수 있도록 하려면 얘도 open으로 열어줘야함
        println("킹")
    }
}

class Secondary : BaseClass() {

    override fun role() {
        super.role() //super : 기본적으로 BaseClass에서 정의한 내용을 실행하란뜻

        print("세자 입니다")
    }

}

참고
super 함수를 닫으면 당연히 부모에서 정의함 role 안나옴
super는 부모의 함수를 부르는 것이기 떄문

class Secondary : BaseClass() {

    override fun role() {
        //super.role() //super : 기본적으로 BaseClass에서 정의한 내용을 실행하란뜻

        print("세자 입니다")
    }

}

인터페이스

함수나 속성을 사용하겠다는 뜻
인터페이스는 open 키워드를 사용할 필요가 없이 상속이 가능하다
인터페이스를 구현하려면 함수를 구현하고 오버라이딩해야한다

interface Archery {
    fun archery() {
        println("아아아")
    }
}

interface Singer {
    fun sing() {
        println("가수")
    }
}

class Offspring : Secondary(), Archery, Singer {
    override fun archery() {
        super.archery()
    }

    override fun sing() {
        super.sing()
    }

    override fun role() {
        super.role()
    }
}

fun main() {

    val obj4 = Offspring()
    obj4.role()
    obj4.archery()
    obj4.sing()

}

왜? 인터페이스를 사용해야할까?

  1. 추상화
    인터페이스는 클래스가 구현할수 있는 계약을 정의할 수 있게 하는데 이 계약을 파생 클래스가 반드시 구현해야하는 메소드로 구성되어있으며 무엇을 어떻게 할지 추상화함, 어떻게 할지는 지금 당장 정하지 않으면서 클래스가 특정 기능을 갖게 할 수 있다

  2. 다중상속
    객체지향 언어는 단일 상속만 가능한데 이러한 한계를 극복하기 위해 인터페이스를 사용하면 다중 상속이 가능하다

  3. 유연성과 호환성
    다양한 방법으로 같은 인터페이스를 구현한 여러 클래스를 만들수 있다
    그 클래스들의 객체는 연관된 인터페이스에 의해 가능성이 보장된다면 콘텍스트에서 상호 교환적으로 사용할 수 있다

  4. 캡슐화
    클래스 내부 구현 사항을 숨길 수 있어 인터페이스에서 선언한 매소드만 노출할 수 있다

  5. 확장성
    소프트웨어가 커지면 인터페이스는 인터페이스에 따른 클래스에 영향을 주지 않고도 기본이 되는 규현을 확장하고 리팩토링 할 수 있다

profile
보조기억장치

0개의 댓글