Study Record

[Kotlin] Extensions 살펴보기 본문

안드로이드/Kotlin

[Kotlin] Extensions 살펴보기

초코초코초코 2023. 8. 18. 01:10
728x90

😶 Extensions 살펴보기

상속하거나 데코레이터와 같은 디자인 패턴을 사용할 필요 없이 새로운 기능을 가진 인터페이스를 확장할 수 있는 기능을 Extensions 을 통해 수행할 수 있다. 수정할 수 없는 클래스 혹은 타사 라이브러리 인터페이스에 대해 새로운 함수를 작성할 수 있다.

 

Extensions Function(확장 함수)의 예시는 다음과 같다. 예시 테스트 클래스의 확장 함수는 이름 앞에 테스트 클래스의 이름을 적고 점(.)으로 확장 함수의 이름으로 나머지 함수를 정의하면 된다. this 키워드로 확장하는 클래스를 참조할 수 있다.

class TestClass<T>(val member: T) {
    fun printLine() {
        println("TestList Class 의 printLine() 실행")
    }
}

// Extensions Function
fun <T> TestClass<T>.printMember(): T {
    println("member is ${this.member}")
    return this.member
}

fun TestClass<Int>.getSquareMember(): Int {
    return this.member * this.member
}

fun main() {
    val testIntClass = TestClass<Int>(5)
    val testStringClass = TestClass<String>("hello")

    testStringClass.printLine()
    testIntClass.printMember()
    println("testIntClass.getSquareMember() is ${testIntClass.getSquareMember()}")

}

 

만약 확장 함수의 이름이 본 클래스의 메서드 이름과 같다면 볼 클래스의 함수가 호출된다. 하지만 파라미터 조건이 다르면 서로 다른 메서드로 인식된다.

class Example {
    fun printFunctionType() { println("Class method") }
}

fun Example.printFunctionType() { println("Extension Function") }
fun Example.printFunctionType(i: Int) { println("Extension function #$i") }

fun main() {
    Example().printFunctionType()
    Example().printFunctionType(1)
}

/* 실행 결과
Class method
Extension function #1
*/

 

 

😶 null 가능

Extension Function 을 선언할 때 ? 와 함께 다음과 같이 사용할 수 있다. 이는 인스턴스가 확장 함수를 호출할 때 null 이어도 실행할 수 있다.

class Example

fun Example?.getString() : String {
    if(this == null) return "Example is null"
    return "Example is not null"
}

fun main() {
    val example : Example? = null
    println(example.getString())
}

 

 

😶 Extension Properties (확장 속성)

Extension Property 를 선언할 수 있지만 실제로 클래스에 멤버로서 간주되지 않기 때문에 다음과 같은 형태만 가능하다. 데이터도 저장할 수 없는 get-only 형태이다. backing field, initializers 모두 가질 수 없다.

class Example(val name: String) {}

val Example.extension: String
    get() = "my name is $name"

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

 

 

😶 Companion Object Extensions

클래스에 companion object 가 정의된 경우 companion objcet 에 대한 확장 함수도 정의할 수 있다.

class MyClass {
    companion object { }  // will be called "Companion"
}

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

fun main() {
    MyClass.printCompanion()
}

 

 

😶 클래스 내부에 확장 함수 선언하기

한 클래스안에 다른 클래스의 확장 함수를 선언할 수 있다. 함수 이름이 같은 경우 this 키워드로 어떤 클래스의 메서드를 호출할 것인지 명시할 수 있다.

class Host(val hostname: String) {
    fun printHostname() { print(hostname) }
    fun printPort() { print("null") }
}

class Connection(val host: Host, val port: Int) {
    fun printPort() { print(port) }

    fun Host.printConnectionString() {
        printHostname()   // calls Host.printHostname()
        print(":")
        // this.printPort()  // calls Host.printPort()
        this@Connection.printPort()   // calls Connection.printPort()
    }

    fun connect() {
        /*...*/
        host.printConnectionString()   // calls the extension function
    }
}

fun main() {
    Connection(Host("kotl.in"), 443).connect()
    // error, the extension function is unavailable outside Connection
    //Host("kotl.in").printConnectionString() 
}

/* 실행결과
kotl.in:443
*/

 

 

Extensions | Kotlin

 

kotlinlang.org

 

728x90