- 클래스::class
- 인스턴스::class
코틀린 리플랙션 객체는 자바 리플랙션 객체와는 다르다.
코틀린 내부에서 컴파일 과정에서 도출된 메타 데이터를 가지고 있음
- Collection<KCallable<*>> 로 표현된다.
-List, Set, Map 모두 Collection 을 가르킨다.
- KProperty: 속성
- KFunction: 함수, 메서드
코틀린은 클래스의 속성을 만들면 값이 아니라 getter/setter 를 만드는 메소드로 인식 ?? 속성을 만드는 것 자체가 getter/setter 를 만드는 것과 같다.
- 필터는 걸러낼 뿐이지 여전히 it 은 KCallable 이다.
- "문(Statement)" 은 컴파일 되고 난뒤, CPU 에 내리는 명령으로 바뀜
- "식(Expression)" 은 컴파일 되고 난뒤, 메모리에 올라가는 값으로 바뀜. -> 식은 값으로 규결된다.
함수형 언어는 Statement 를 Expression 으로 바꾸는 케이스가 많다.
예를들어 루비는 statemenet 가 없다.
Statement 는 한번 실행하면 끝나고, 여러번 실행시킬수 없고 제어하기 힘들다. 그리고 Runtime 에 유언성을 확보하기 위해 Expression 으로 많이 바꿈.
코틀린은 문을 해석하는 순서가 위에서 아래로 향한다.
위에서 타입을 확정지으면, 아래 코드는 그것을 받아들인다.
즉 위 코드처럼 위에서 null 을 체크했기 때문에 아래 코드에서는 null 을 체크하지 않는다.
Java 나 C 의 Switch, case 문은 바이트코드로 해석이 되거나 어셈블리가 작동할때 router map 처럼 작동하기 때문에
동시에 그 값이 어디로 들어갈지 분기처리를 한디.
하지만 코틀린은 위에서 아래로 순차적으로 해석한다. 그래서 스마트캐스팅이 가능하다.
단점으로는 케이스가 너무 많다면 코틀린은 부하가 생길 수 밖에 없다. 반면에 Java 나 C 는 부하가 증가하지 않는다.
그렇기 때문에 많이 걸리는 케이스들을 위로 올리는 것이 유리하다.
코드의 중복이라는 것은 존재하는 것이 아니라 발견되는 것이다 - 구현패턴, 캔트백
fun <T : Any> jsonObject(target: T): String {
val builder = buildString {
target::class.members
.filterIsInstance<KProperty<*>>()
.joinTo(buffer = this, separator = ", ", prefix = "{", postfix = "}") {
val value = it.getter.call(target)
"${jsonString(it.name)} : ${when (value) {
null -> "null"
is String -> jsonString(value)
is Boolean, is Number -> value.toString()
is List<*> -> jsonList(value)
else -> jsonObject(value)
}}"
}
}
return builder
}
fun <T : Any> jsonObject(target: T): String {
val builder = buildString {
target::class.members
.filterIsInstance<KProperty<*>>()
.joinTo(buffer = this, separator = ", ", prefix = "{", postfix = "}") {
"${jsonValue(it.name)} : ${jsonValue(it.getter.call(target))}"
}
}
return builder
}
함수의 레퍼러스를 얻는 방법: :: 함수, 인스턴스::메소드
리플랙션으로 함수의 레퍼런스를 얻는 다는 것은 기존의 레퍼런스를 얻는 것이 아닌 메소드를 호출하는 새로운 람다를 생성하는 것이다. (자바로 마찬가지)
Extension Function 에 접근제한자를 private 으로 걸면 그 function 은 해당 파일내에서만 사용 가능하다.
프로그래밍은 세부적으로 작성할 수록 범용성이 떨어진다.
확장 함수로 마음껏 오버로딩이 가능하다
모든 객체라면 위 4개 확장함수를 사용할 수 있다.
코드를 트랜잭션 블록을 선언하는 것과 같다 ?? <- 건들 수 없는 블록
메소드 체이닝이 안되는 객체도 apply 를 통해 메소드 체이닝이 가능해진다. 왜냐하면 확장함수 형태로 들어오기 때문에 ??
코틀린에서는 return this 를 하지 않고 apply 를 사용해도된다.
확장함수 형태가 아닌 인자로 넘어온다.
코드 외적으로 힌트를 추가하는 메타프로그래밍이라고 볼 수 있다.
Annotation 의 장점은 기존 로직에 아무런 영향도 없다.
자바는 바이너리로 애노테이션을 저장하기 때문에 런타임에 사용할 수 없다. 그래서 특수한 ?? 기능을 사용하여 다룰 수 있음
코틀린은 기본 값이 런타임이라 실행 중에 언제든지 값을 얻어낼 수 있다.
애노테이션의 단점 -> 코드 힌트가 되지 않아 존재 조차 모를 수 있음