고차 함수를 사용하면 특정 런타임 패널티가 부과됩니다. 각 함수는 객체이며 클로저, 즉 함수 본문에서 액세스되는 변수를 캡처합니다. 메모리 할당 (함수 객체와 클래스 용)과 가상 호출은 런타임 오버 헤드를 초래합니다.
그러나 많은 경우에 이런 종류의 오버 헤드는 람다식을 인라인함으로써 제거 될 수 있습니다. 아래에 표시된 함수는이 상황의 좋은 예입니다. 즉,이 lock()
기능은 전화 사이트에서 쉽게 인라인 될 수 있습니다. 다음과 같은 경우를 고려하십시오.
lock(l) { foo() }
매개 변수에 대한 함수 객체를 만들고 호출을 생성하는 대신 컴파일러에서 다음 코드를 생성 할 수 있습니다.
l.lock()
try {
foo()
}
finally {
l.unlock()
}
우리가 처음부터 원한 것이 아닌가?
컴파일러가이를 수행하게하려면 수정 자로 lock()
함수 를 표시해야합니다 inline
.
inline fun lock<T>(lock: Lock, body: () -> T): T {
// ...
}
inline
수정은 함수 자체에 전달 된 람다 모두에 영향을 미칩니다 : 그 모든 호출 사이트에 인라인됩니다.
인라인하면 생성 된 코드가 커질 수 있습니다. 그러나 합리적인 방법으로 (즉, 큰 기능을 인라인하지 않아도) 루프를 수행하면 성능면에서 효과가 있으며 특히 루프 내부의 "거대 (megamorphic)"호출 사이트에서 효과가 있습니다.
노 인라인
인라인 함수에 전달 된 람다 중 일부만 인라인되도록하려면 다음과 같이 함수 매개 변수 중 일부를 noinline
수정 자로 표시 할 수 있습니다 .
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
// ...
}
Inlinable lambdas는 인라인 함수 안에서만 호출되거나 인라인 가능 인자로 전달 noinline
될 수 있지만, 우리는 우리가 좋아하는 어떤 방식 으로든 조작 될 수 있습니다 : 필드에 저장되고, 전달됩니다.
인라인 함수에 인라인 가능 함수 매개 변수가없고 구체화 된 유형 매개 변수가없는 경우 컴파일러에서 해당 함수를 인라인하면 매우 유용하지 않으므로 컴파일러에서 경고를 표시합니다 (인라인 함수를 사용하여 인라인이 필요하다고 확신하는 경우 경고를 표시하지 않을 수 있습니다). 주석 @Suppress("NOTHING_TO_INLINE")
).
비-로컬 리턴
코틀린에서는 return
명명 되지 않은 함수 나 익명의 함수를 종료하기 위해 정규화되지 않은 정규화 된 함수 만 사용할 수 있습니다 . 즉, 람다를 종료하려면 레이블 을 사용해야하고 람다에서는 베어 return
함수를 반환 할 수 없기 때문에 람다 안에서 베어 를 금지합니다.
fun foo() {
ordinaryFunction {
return // 에러: 'foo'를 리턴할 수 없습니다.
}
}
그러나 lambda가 전달 된 함수가 인라인되면, 리턴도 인라인 될 수 있으므로 허용됩니다.
fun foo() {
inlineFunction {
return // OK: 람다도 인라인 가능합니다.
}
}
이러한 반환 값 (람다에 있지만 둘러싸는 함수를 빠져 나옴)을 비 로컬 리턴 이라고 합니다. 우리는 인라인 함수가 자주 묶는 이러한 종류의 루프에 익숙합니다.
fun hasZeros(ints: List<Int>): Boolean {
ints.forEach {
if (it == 0) return true // hasZoros에서 리턴합니다.
}
return false
}
일부 인라인 함수는 매개 변수로 전달 된 lambdas를 함수 본문에서 직접 호출하지 않고 로컬 객체 나 중첩 함수와 같은 다른 실행 컨텍스트에서 호출 할 수 있습니다. 이러한 경우, 람다에서는 비 로컬 제어 흐름도 허용되지 않습니다. 이를 나타 내기 위해, lambda 매개 변수를 crossinline
수정 자로 표시해야합니다 .
inline fun f(crossinline body: () -> Unit) {
val f = object: Runnable {
override fun run() = body()
}
// ...
}
break
및continue
인라인 람다에서 아직 사용할 수 없습니다, 그러나 우리는 그들도 지원할 계획이다.
구체화 된 유형 매개 변수
때때로 우리에게 전달 된 타입을 매개 변수로 접근해야한다 :
fun <T> TreeNode.findParentOfType(clazz: Class<T>): T? {
var p = parent
while (p != null && !clazz.isInstance(p)) {
p = p.parent
}
@Suppress("UNCHECKED_CAST")
return p as T?
}
여기서는 트리를 걸어 리플렉션을 사용하여 노드에 특정 유형이 있는지 확인합니다. 괜찮아요.하지만 전화 사이트는별로 예쁘지 않습니다.
treeNode.findParentOfType(MyTreeNode::class.java)
우리가 실제로 원하는 것은이 함수에 형식을 전달하는 것입니다. 즉, 다음과 같이 호출하십시오.
treeNode.findParentOfType<MyTreeNode>()
이를 가능하게하기 위해 인라인 함수는 구체화 된 타입 매개 변수를 지원 하므로 다음과 같이 작성할 수 있습니다 :
inline fun <reified T> TreeNode.findParentOfType(): T? {
var p = parent
while (p != null && p !is T) {
p = p.parent
}
return p as T?
}
type 매개 변수를 reified
수식어로 수식 했으므로 이제 함수 내부에서 일반 클래스처럼 액세스 할 수 있습니다. 함수가 인라인되어 있기 때문에, 더 반사는 정상처럼 사업자, 필요하지 않습니다 !is
그리고 as
지금 노력하고 있습니다. 또한 위에서 언급 한대로 호출 할 수 있습니다 myTree.findParentOfType<MyTreeNodeType>()
.
많은 경우 리플렉션이 필요하지 않을 수 있지만 구체화 된 유형 매개 변수로 리플렉션을 사용할 수 있습니다.
inline fun <reified T> membersOf() = T::class.members
fun main(s: Array<String>) {
println(membersOf<StringBuilder>().joinToString("\n"))
}
일반 함수 (인라인으로 표시되지 않음)는 매개 변수를 구체화 할 수 없습니다. 런타임 표현이없는 유형 (예 : 비 구체화 된 유형 매개 변수 또는 가상의 유형 Nothing
)은 구체화 된 유형 매개 변수에 대한 인수로 사용할 수 없습니다.
낮은 수준의 설명은 사양 문서를 참조하십시오 .
인라인 속성 (1.1 이후)
inline
수정은 백업 필드가없는 속성의 접근에 사용할 수 있습니다. 개별 속성 접근 자에 주석을 달 수 있습니다.
val foo: Foo
inline get() = Foo()
var bar: Bar
get() = ...
inline set(v) { ... }
모든 접근자를 인라인으로 표시하는 전체 속성에 주석을 달 수도 있습니다.
inline var bar: Bar
get() = ...
set(v) { ... }
호출 사이트에서 인라인 접근자는 일반 인라인 함수로 인라인됩니다.
공용 API 인라인 함수의 제한 사항
인라인 함수가 public
또는 또는 선언 protected
의 일부가 아닌 인라인 함수는 모듈 의 공용 API로 간주 됩니다. 다른 모듈에서 호출 할 수 있으며 이러한 호출 사이트에서도 인라인됩니다.private
internal
이것은 호출 모듈이 변경 후에 다시 컴파일되지 않을 경우 인라인 함수를 선언하는 모듈의 변경으로 인해 발생하는 특정 이진 비 호환성 위험을 부과합니다.
이러한 호환성이의 변화에 의해 도입되는 위험 제거하기 위해 비 모듈의 -public API를 공개 API의 인라인 함수는 비공개-API 선언, 즉 사용 할 수 없습니다 private
와 internal
자신의 몸에, 선언과 부품.
internal
로 주석 할 수있다 선언 @PublishedApi
공개 API의 인라인 함수에서 사용을 할 수 있습니다. 때 internal
인라인 함수로 표시되어 @PublishedApi
그것이 공용 것처럼 몸 역시 확인된다.
'프로그래밍 > kotlin' 카테고리의 다른 글
코틀린 - 함수 (0) | 2021.04.18 |
---|---|
코틀린 - 고차 함수와 람다 (0) | 2021.04.18 |
코틀린 - 코루틴 (0) | 2021.04.18 |
코틀린 - 분리 선언 (0) | 2021.04.18 |
컬렉션 : List, Set, Map (0) | 2021.04.18 |