티스토리 뷰

확장

  • 코틀린의 확장 기능을 통해 기존 클래스의 함수(메서드) 및 프로퍼티를 확장 정의하여 사용할 수 있다.
  • 확장 불가 클래스(final) 또는 짧은 범위에서 특정 클래스의 기능을 추가/수정할 경우 유용하다.
  • 호출 시점에 부가 비용이 발생하지 않는다.

확장 함수 (Extension function)

  • [확장 하려는 대상 클래스].함수명() 형식으로 정의한다.
  • 코틀린의 최상위 객체인 Any에 확장 함수를 정의하면 모든 객체에서 사용 가능하다.
  • 확장 함수의 경우 내부에서만 사용할수 있는 private, protected 멤버에는 접근하지 못한다.
  • 확장 함수와 클래스 멤버 함수의 이름이 같은경우 멤버 함수의 우선순위가 더 높기때문에 클래스 내의 멤버 함수가 호출 된다.

 

class Person(val name: String) {
    fun walk() = "person is walking"
}

// 확장 메서드
fun Person.walk() = "unknown function"
fun Person.nameToUpperCase() = this.name.toUpperCase()

fun main() {
    val person: Person = Person("park jin")
    println(person.nameToUpperCase()) // PARK JIN

    // 멤버 메서드가 우선시 됨
    println(person.walk()) // person is walking
}
  • 확장 함수의 this는 확장 하려는 객체(위에서는 Person)을 가리킨다.
  • 확장시 상속을 사용하지 않으며 내부적으로 수신자 클래스를 첫번째 인자로 받는 정적 메서드로 변환한다.
ExtensionsKt.attachStringToBothSide(String);

 

정적 바인딩 vs 동적 바인딩

  • 확장 함수의 경우 오버라이드와 다르게 정적 바인딩 처리된다.
정적 바인딩 vs 동적 바인딩

정적 바인딩: 컴파일 시간에 성격이 결정 된다.
동적 바인딩: 런타임시에 성격이 결정 된다.
확장 함수
open class Person

class Student: Person()

fun Person.name() = "person"
fun Student.name() = "student"

fun printName(person: Person) {
    println(person.name()) // 정적 바인딩되어 person 출력
}

fun main() {
    printName(Student())
}
오버라이드
open class Person {
    open fun printName() = "person"
}

class Student: Person() {
    override fun printName() = "student"
}

fun printName(person: Person) {
    println(person.printName()) // 동적 바인딩 되어 student 출력
}

fun main() {
    printName(Student())
}

확장 프로퍼티 (Extension Property)

  • 기존 객체에 실제로 프로퍼티를 추가하는 방식이 아니기 때문에 상태를 저장할 수는 없음.
  • getter, setter를 추가하여 구현한다.
class Person {
    var friendList = mutableListOf<String>()
}

// 확장 프로퍼티(friend)
var Person.friend: String
    get() = this.friendList.last()
    set(value) { this.friendList.add(value) }


fun main() {
    val person = Person()
    
    person.friend = "park jin1"
    person.friend = "park jin2"
    
    println(person.friend) // park jin2
}

 


출처

...더보기

 

댓글