여기까지 정리 2
- 고차함수란?
- 다른 함수를 파라미터로 받거나 함수를 반환하는 함수
- 코틀린의 람다, 자바의 람다와의 차이?
- 람다가 함수 인자면 트레일링 클로저처럼 뺼 수 있다.
- 람다 인자가 하나면 이름 지정 없이
it로 뺄 수 있다.
- 코틀린의 함수 타입, 자바의 함수형 인터페이스와 차이?
- 함수 타입은 함수처럼 쓰일 수 있는 값들을 표시하는 타입이다.
- 함수 타입은 SAM 인터페이스로 암시적으로 변환할 수 없다.
- 자바의 SAM은 람다나 메소드 참조로 인스턴스화할 수 있다.
SAM(Single Abstract Method)
- 수신 객체가 있는 함수 타입, 없는 함수 타입
- 수신 객체 X: (Int) -> Int
- 수신 객체 O: Int.(Int) -> Int
- 익명 함수와 람다의 차이
- 익명 함수는 fun(parameter)의 형태로 작성하는 이름이 없는 함수
- 인라인 함수와 제약
- inine함수는 컴파일 타임에 해당 선언을 인라인으로 넣어준다. 이러면 오버헤드가 줄어들게 된다.
- 호출 가능 참조
- 람다나 익명함수로 함수 값을 만들었을 때 이미 선언되어 있고 이를 함수로 넘기려면
::functionName으로 넘길 수 있다.
- 람다와 익명 함수 안에서의 return
- 비지역적 반환(non-local return)이 일어난다.
- 비지역적 반환은 특정 블록이나 람다 표현식의 스코프를 벗어나 바깥쪽 함수나 스코프로 반환하는 것을 의미한다.
- 이러면
- 흐름 제어에서 예기치 않은 반환이 일어난다.
- 유지보수가 어려워진다.
- 테스트도 어려워진다.
- 가독성도 떨어진다.
- 안정성이 떨어진다.
- 이러면
- 이 말은 즉, 람다나 익명함수가 컴파일되면 inline이 된다.
- inline, noinline, crossinline
- inline: 컴파일 타임에 코드를 아예 해당 부분에 바로 넣는다.(원래 거기 있는 것처럼)
- noinline: inline을 막는다.
- crossinline: 주로 비지역적 제어흐름을 막기 위해서 사용한다.
- 확장함수란?
- 어떤 클래스의 멤버인 것처럼 호출할 수 있는, 그러나 멤버는 아닌 함수를 의미한다.
- 동반객체확장
- 클래스에 내포된 객체 중에서 바깥 클래스의 이름으로 객체 멤버에 접근할 수 있는 companion 레벨에서 확장하는 것을 의미한다.
Companion을 명시한다.
- 확장 프로퍼티와 제약
- 다른 일반 멤버와 마찬가지로 확장프로퍼티에 접근할 수 있다.
- 그러나 안정적으로 상태를 추가할 방법이 없어서 뒷받침 필드를 사용할 수 없고
- lateinit 등도 불가하다.
- lazy도 (delegate) 쓸 수는 있는데 의미가 없다.
- 명시적 get/set이 필요하다.
- 클래스 내부에서 확장 함수 선언의 주의점?
- 캡슐화는 꺨 수 없지만 시그니쳐가 겹치면 멤버를 먼저 콜해서 원하는 대로 동작하지 않을 수 있다.
- 영역 함수란?
-
apply, with, let, also, run 등이 있다.
inline fun <T, R> with(receiver: T, block: T.() -> R): R { return receiver.block() } inline fun <T> T.also(block: (T) -> Unit): T { block(this) return this } inline fun <T> T.apply(block: T.() -> Unit): T { block() return this } inline fun <T, R> T.let(block: (T) -> R): R { return block(this) } inline fun <T, R> T.run(block: T.() -> R): R { return block() } /** * with, also, apply, let, run은 3가지 차이점 중 한 가지가 서로 다르다. * 1. 범위 지정 함수 호출 시 수신 객체가 매개 변수로 명시적으로 전달되거나 수신 객체의 확장 함수 형태로 암시적 수신 객체로 전달 * 2. 범위 지정 함수의 수신 객체 지정 람다에 전달되는 수신 객체가 명시적으로 매개 변수로 전달되거나 수신 객체의 확장 함수로 암시적인 수신 객체로 코드 블록 내부로 전달 * 3. 범위 지정 함수의 결과로 수신 객체를 그래로 반환하거나 수신 객체 지정 람다의 실행 결과 반환 **/- apply 사용 예시: 수신 객체 람다 내부에서 수신 객체의 함수를 사용하지 않고 수신 객체를 다시 반환하려는 경우
- also 사용 예시: 수신 객체의 프로퍼티나 함수 대신에 객체 자기 자신에 대한 참조가 필요한 경우
- let 사용 예시: null safety 체크에서 많이 사용
- with 사용 예시: NonNull 수신객체이고 결과가 필요하지 않은 경우
- run 사용 예시: 값을 계산할 필요가 있거나 여러 개의 지역 변수 범위를 제한하려고 할 떄
-