Hanbit the Developer
Kotlin Documentation | Extensions 본문
Category: Concepts - Classes and objects
문서 링크: https://kotlinlang.org/docs/extensions.html
데코레이터 패턴, 상속 없이 클래스, 인터페이스를 확장할 수 있다:
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp
}
Extensions are resolved statically
멤버를 추가하는 것이 아니라, statically하게 작동한다.(런타임 때의 타입으로 작동하는 게 아니다.):
open class Shape
class Rectangle: Shape()
fun Shape.getName() = "Shape"
fun Rectangle.getName() = "Rectangle"
fun printClassName(s: Shape) {
println(s.getName())
}
printClassName(Rectangle())
Shape
런타임에서 Rectangle 인스턴스가 함수가 들어갔음에도 Shape.getName()을 호출한다.
같은 함수가 있을 때 멤버 함수의 우선순위가 더 높다:
class Example {
fun printFunctionType() { println("Class method") }
}
fun Example.printFunctionType() { println("Extension function") }
Example().printFunctionType()
Class method
Nullable receiver
fun Any?.toString(): String {
if (this == null) return "null"
// after the null check, 'this' is autocast to a non-null type, so the toString() below
// resolves to the member function of the Any class
return toString()
}
Extension properties
val <T> List<T>.lastIndex: Int
get() = size - 1
val House.number = 1 // error: initializers are not allowed for extension properties
Companion object extensions
fun MyClass.Companion.printCompanion() { println("companion") }
Scope of extensions
대부분 패키지의 top-level에 확장 함수를 선언한다:
package org.example.declarations
fun List<String>.getLongestString() { /*...*/}
이를 사용하기 위해 import가 필요하다:
package org.example.usage
import org.example.declarations.getLongestString
fun main() {
val list = listOf("red", "green", "blue")
list.getLongestString()
}
Declaring extensions as members
class Host(val hostname: String) {
fun printHostname() { print(hostname) }
}
class Connection(val host: Host, val port: Int) {
fun printPort() { print(port) }
**fun Host.printConnectionString() {
printHostname() // calls Host.printHostname()
print(":")
printPort() // calls Connection.printPort()
}**
fun connect() {
/*...*/
**host.printConnectionString() // calls the extension function**
}
}
fun main() {
**Connection(Host("kotl.in"), 443).connect()
// Host("kotl.in").printConnectionString() // error, the extension function is unavailable outside Connection**
}
class Connection {
fun Host.getConnectionString() {
toString() // calls Host.toString()
this@Connection.toString() // calls Connection.toString()
}
}
open class Base { }
class Derived : Base() { }
open class BaseCaller {
open fun Base.printFunctionInfo() {
println("Base extension function in BaseCaller")
}
open fun Derived.printFunctionInfo() {
println("Derived extension function in BaseCaller")
}
fun call(b: Base) {
b.printFunctionInfo() // call the extension function
}
}
class DerivedCaller: BaseCaller() {
override fun Base.printFunctionInfo() {
println("Base extension function in DerivedCaller")
}
override fun Derived.printFunctionInfo() {
println("Derived extension function in DerivedCaller")
}
}
fun main() {
BaseCaller().call(Base()) // "Base extension function in BaseCaller"
BaseCaller().call(Derived()) // "Base extension function in BaseCaller"
DerivedCaller().call(Base()) // "Base extension function in DerivedCaller" - dispatch receiver is resolved virtually
DerivedCaller().call(Derived()) // "Base extension function in DerivedCaller" - extension receiver is resolved statically
}
'Kotlin' 카테고리의 다른 글
Kotlin Documentation | Sealed classes and interfaces (0) | 2023.05.23 |
---|---|
Kotlin Documentation | Data classes (0) | 2023.05.23 |
Kotlin Documentation | Visibility modifiers (0) | 2023.05.22 |
Kotlin Documentation | Functional (SAM) interfaces (0) | 2023.05.22 |
Kotlin Documentation | Interfaces (0) | 2023.05.22 |