// MutableList<Int>가 수신 객체 타입이 된다.
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
}
open class Shape
class Rectangle : Shape()
fun Shape.getName() = "Shape"
fun Rectangle.getName() = "Rectangle"
fun main() {
val shape: Shape = Rectangle()
println(shape.getName()) // 결과는 "Shape"
}
class Shape {
fun getName() = "멤버 함수 Shape"
}
fun Shape.getName() = "확장 함수 Shape"
val s = Shape()
println(s.getName()) // 결과는 "멤버 함수 Shape"
class Example {
fun printFunctionType() { println("Class method") }
}
fun Example.printFunctionType(i: Int) { println("Extension function #$i") }
Example().printFunctionType(1) // "Extension function 1"
fun Any?.toString(): String {
if (this == null) return "null"
return toString()
}
val <T> List<T>.lastIndex: Int
get() = size - 1
class MyClass {
companion object { }
}
fun MyClass.Companion.printCompanion() { println("companion") }
fun main() {
MyClass.printCompanion()
}
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() // Host의 멤버 호출
print(":")
printPort() // Connection의 멤버 호출
}
fun connect() {
host.printConnectionString()
}
}
fun main() {
Connection(Host("kotl.in"), 443).connect()
// 결과: kotl.in:443
// Host("kotl.in").printConnectionString(443) // 오류: 확장 함수는 Connection 안에서만 호출 가능
}
this@{className}
형태로 디스패치 리시버 멤버에 접근할 수는 있다.class Connection {
fun Host.getConnectionString() {
toString() // Host.toString() 호출
this@Connection.toString() // 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()
}
}
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"
DerivedCaller().call(Base()) // "Base extension function in DerivedCaller"
DerivedCaller().call(Derived()) // "Base extension function in DerivedCaller" (여기가 포인트)
}
BaseCaller
와 DerivedCaller
는 디스패치 리시버, Base
, Derived
는 확장 리시버이다.
DerivedCaller().call(Derived())
에서 호출되는 함수는DerivedCaller
에서 오버라이드한Base.printFunctionInfo()
이다. (“Base extension function in DerivedCaller”)Derived
가 전달되었지만 call(b: Base)
에서b
의 타입이Base
로 정해져 있으므로, 확장 리시버 타입(Base
) 기준으로만 확장 함수가 호출된다.DerivedCaller
)는 virtual하게 선택되지만, 확장 리시버(Base
/Derived
)는 static하게 선택된다.