Kotlin의 확장함수(Extension)

Kotlin Extension

https://kotlinlang.org/docs/extensions.html

 

Extensions | Kotlin

 

kotlinlang.org

Kotlin은 클래스에서 상속하거나 새로운 디자인 패턴을 사용하지 않고도 새로운 기능으로 클래스나 인터페이스를 확장할 수 있는 기능을 제공합니다.

이는 Extensions 라는 특수 선언을 통해 수행됩니다.

수정할 수 없는 타사 라이브러리의 클래스 또는 인터페이스에 대한 새 함수를 작성할 수 있으며,

함수를 마치 원래 클래스의 메서드인 것처럼 일반적인 방법으로 호출할 수 있습니다.

이를 extension function이라고 하며, 기존 클래스에 대한 새 속성을 정의할 수 있는 extension properties도 있습니다.

 

extension function

확장 함수를 선언하려면 확장되는 유형을 참조하는 수신사 유형을 이름 앞에 붙입니다.

fun MutableList<Int>.swap(index1: Int, index2: Int) {
	val tmp = this[index1]
    this[index1] = this[index2]
    this[index2] = tmp 
}

this 키워드를 통해서 수신자 객체 (여기서는 MutableList)에 접근할 수 있으며, swap 함수를 MutableList에 추가할 수 있습니다.

any 타입과 같은 MutableList<T>를 통하여 모든 MutableList 수신자 객체에 대한 일반화를 진행할 수 있습니다.

여기서 중요한 특징은 extension은 정적으로 수행된다는 것입니다.

실제로 확장하는 클래스를 수정하지 않으며, 클래스에 새 멤버를 삽입하지 않고 새 함수를 만드는 것입니다.

어떤 확장 함수가 호출되는지는 수신자 유형에 따라 컴파일 타임에 이미 알려지게 됩니다.

다른 특징으로는 클래스 멤버 함수가 있고 동일한 수신자 유형과 동일한 이름을 가진 확장함수가 선언되는 경우 멤버 함수에 우선순위가 부여됩니다.

class Example {
	fun printFunctionType() = print("class")
}

fun Example.printFunctionType() = print("extension")

Example().printFunctionType()

// output class

 

Nullable receiver

nullable receiver type 역시 선언할 수 있습니다.

fun Any?.toString() : String {
	if (this == null) throw Exception("is Null")
	return toStirng()
}

nullable 객체에 대해서는 항상 this == null의 가능성이 있으므로, 예외 검사를 해주는 것이 좋습니다.

 

Extension properties

val <T> List<T>.lastIndex: Int
    get() = size - 1

function과 마찬가지로, 확장 property를 선언할 수 있습니다.

실제로 클래스에 멤버를 삽입하지 않으므로 확장 속성에 backing field를 포함하는 효율적인 방법은 존재하지 않습니다.

이는 확장 속성에 초기화 프로그램이 허용되지 않는 이유입니다.

반드시 해당 동작은 getter/setter를 명시적으로 제공해야 합니다.

val House.number = 1 // error: initializers are not allowed for extension properties

확장 속성을 제공하는 경우 초기화를 진행하면, extension properties에는 에러가 발생합니다. 

 

Companion object extensions

만약 클래스에 동반 객체가 정의되어 있는 경우, 동반 객체에 대한 확장 함수 및 속성을 정의할 수도 있습니다.

동반 객체의 일반 멤버와 마찬가지로 클래스 이름만 한정자로 사용하여 호출할 수 있습니다.

class MyClass {
	companion object { }
}

fun MyClass.Companion.printCompanion() {
	print("companion")
}

 

참고 

https://medium.com/til-kotlin-ko/kotlin%EC%9D%98-extension%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94%EA%B0%80-part-1-7badafa7524a