[Android/Kotlin] 상속과 위임 feat. ViewBinding

곽의진·2023년 10월 13일
0

Android

목록 보기
11/16

✅ 상속 (Inheritance)

상속은 기본적으로 객체 지향 프로그래밍의 핵심 개념 중 하나로, 하나의 클래스가 다른 클래스의 속성 및 메서드를 이어받아 사용하는 것을 의미합니다.

✓ 기본 상속의 사용

Kotlin에서는 :를 사용해 상속을 표현합니다.

open class Parent {
    fun parentFunction() {
        println("This is a parent function")
    }
}

class Child : Parent()

fun main() {
    val child = Child()
    child.parentFunction() // This is a parent function
}

✅ 여기서 open 키워드는 Parent 클래스가 상속 가능하다는 것을 나타냅니다. Kotlin에서는 기본적으로 모든 클래스가 final로 선언되어 있어, 상속을 위해서는 open을 명시해야 합니다.

✅ 위임 (Delegation)

위임은 특정 객체의 기능이나 속성의 사용 권한을 다른 객체에게 넘기는 패턴을 의미합니다. Kotlin에서는 위임 패턴을 쉽게 구현할 수 있도록 by 키워드를 제공합니다.

Property 위임

Kotlin에서 속성 위임은 프로퍼티의 getter와 setter를 다른 객체로 위임하는 것입니다.

class Example {
    var p: String by Delegate()
}

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }
}

위임을 사용한 구현(Inheritance by Delegation)

상속은 "is-a" 관계를 의미합니다. 예를 들어 Bird는 Animal이라고 할 수 있습니다. 하지만 때로는 "has-a" 관계로도 많은 일을 수행할 수 있습니다.

예를 들어, Car는 Engine을 갖고 있다고 할 수 있죠. 위임은 이 "has-a" 관계를 활용하여 특정 객체의 기능을 다른 객체에 위임하는 것을 말합니다.

interface Engine {
    fun start()
    fun stop()
}

class DieselEngine : Engine {
    override fun start() {
        println("Diesel Engine started!")
    }

    override fun stop() {
        println("Diesel Engine stopped!")
    }
}

class ElectricEngine : Engine {
    override fun start() {
        println("Electric Engine started!")
    }

    override fun stop() {
        println("Electric Engine stopped!")
    }
}

1. Car 클래스 생성 및 Engine 위임

Car 클래스는 Engine의 기능을 필요로 합니다. 그러나 Car 자체가 엔진을 어떻게 시작하고, 어떻게 멈추는지 알 필요는 없습니다. 대신, 그 일을 Engine 구현체에게 위임합니다.

class Car(engine: Engine) : Engine by engine

이렇게 하면 Car는 start와 stop 메서드를 직접 구현할 필요가 없습니다. 대신, 생성 시점에 어떤 엔진을 사용할지 결정하고 그 엔진의 start와 stop을 호출하게 됩니다.

2. 메인 함수에서의 사용

fun main() {
    val dieselCar = Car(DieselEngine())
    val electricCar = Car(ElectricEngine())

    dieselCar.start()    // 출력: Diesel Engine started!
    electricCar.start()  // 출력: Electric Engine started!
    
    dieselCar.stop()     // 출력: Diesel Engine stopped!
    electricCar.stop()   // 출력: Electric Engine stopped!
}

결과적으로 Car는 어떤 종류의 엔진을 갖고 있는지 알 필요가 없습니다. 단순히 주어진 엔진의 기능을 사용(위임)하면 됩니다. 이렇게 위임을 활용하면, 코드의 재사용성이 향상되고 확장성 또한 높아집니다.

✅ Android ViewBinding에서 활용하기

위임을 활용한 ViewBinding

inline fun <T : ViewBinding> AppCompatActivity.viewBinding(
    crossinline inflater: (LayoutInflater) -> T,
) = lazy(LazyThreadSafetyMode.NONE) {
    inflater.invoke(layoutInflater)
}

이 함수는 viewBinding이라는 확장 함수로, AppCompatActivity에 적용됩니다. 제네릭 타입 T를 사용하여 뷰 바인딩의 타입을 유동적으로 받아올 수 있습니다. lazy delegate 활용하여 뷰 바인딩 객체가 필요할 때만 초기화됩니다.

사용 방법

class MainActivity : AppCompatActivity() {
    private val binding by viewBinding(ActivityMainBinding::inflate)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        // 나머지 로직
    }
}

MainActivity에서는 viewBinding 확장 함수를 활용하여 ActivityMainBinding을 쉽게 초기화할 수 있습니다.

✅ 결론

상속은 클래스 간의 관계를 구축하고, 코드 재사용을 가능케 하는 반면, 위임은 코드의 복잡성을 줄이고, 런타임에 동작을 변경하는 등 유연한 코드 구조를 도와줍니다. 이 두 개념은 모두 코드의 재사용성을 향상시키는 데 있어 중요한 역할을 하므로, 적절히 혼용하여 효율적인 코드 설계를 진행하는 것이 중요합니다.

profile
Android Developer

0개의 댓글