일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 디자인패턴 #
- El
- 디자인패턴
- 싱글톤
- PrototypePattern
- builderPattern
- a
- 추상팩토리패턴
- ㅓ
- 프로토타입 패턴
- 추상 팩토리
- designPattern
- r
- ㅋㅁ
- factory method
- 팩토리 메소드
- F
- 빌터패턴
- Singleton
- Functional Programming
- 함수형프로그래밍
- 코틀린
- Observer Pattern
- Design Pattern
- 옵저버 패턴
- Abstract Factory
- Kotlin
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
애노테이션과 리플렉션 본문
지금까지는 클래스와 함수를 사용하는 여러 코틀린의 특성을 보았다.
이들 모두는 정확한 이름을 알고 있어야 호출/사용 할 수 있었다.
애노테이션과 리플렉션을 사용한다면, 이런 제약을 벗어나 임의의 클래스를 다룰수있다
애노테이션을 이용하면 라이브러리가 요구하는 의미를 클래스에 부여할 수 있다.
리플랙션을 사용하면 실행 시점에 컴파일러 내부구조를 분석할수있다.
애노테이션은 적용하기는 쉽다, 하지만 만들기는 어렵다. 특히 애노테이션을 처리하는 코드는 더 어렵다.
애노테이션 선언과 적용
메타데이터를 선언에 추가하면 애노테이션을 처리하는 도구가컴파일 시점이나 실행 시점에 적절한 처리를 해준다.
@+name 형태
예) Junit
class MyTest{
@Test fun testTrue() {
Assert.assertTrue(true)
}
}
사용금지를 설명하고 대체할 패턴을 제시한다.
@Deprecated("Use removeAt(index) instead", ReplaceWith("removeAt(index)"))
fun remove(index: Int){ ... }
애노테이션에 인자를 넘길 때는 일반 함수와 마찬가지로 괄호 안에 인자를 넣어 넘긴다.
remove를 호출하는 코드에 대해 경고 메세지를 제공하고 자동으로 그 코드를 새로운 API버전에 맞는 코드로 바꿔주는 퀵 픽스도 제공한다.
애노테이션의 인자에는 원시타입값, 문자열, enum, 클래스참조, 다른 애노테이션 클래스, 앞의 타입들을 원소로 하는 배열이 들어갈 수 있다.
- 클래스를 애노테이션 인자로 지정할때는 @MyAnnotation(MyClass::class) ::class 붙혀줘야된다.
- 다른 애노테이션을 인자로 지정할때는 이름 앞에 @를 넣지 않는다. 위의 코드에서 ReplaceWith도 애노테이션이다.
- 배열을 인자로 지정하려면, @RequestMapping(path = arrayOf("/foo" , "/bar")) 처럼 arrayOf 함수를 사용한다.
*자바에서 지정한 애노테이션 클래스를 이용한다면, value라는 이름의 가변 길이 인자로 변환된다, 따라서 @JavaAnnotationWithArrayValue("abc", "foo", "bar")처럼 arrayOf함수를 안써도 된다.
애노테이션 인자를 컴파일 시점에 알 수 있어야 한다. 따라서 임의의 프로퍼티를 인자로 지정할 수는 없다. 프로퍼티를 애노테이션으로 사용하려면, 컴파일러는 const가 붙은 프로퍼티를 컴파일 시점에 상수로 취급한다. 그래서 const를 붙혀줘야된다.
const val TEST_TIMEOUT = 100L
@Test(timeout = TEST_TIMEOUT) fun testMethod(){ ... }
const가 붙은 프로퍼티는 파일의 최상위나 object안에 선언 해야 하며 원시타입 또는 String으로만 초기화가 가능하다.
애노테이션의 대상
코틀린 소스코드에서 한 선언을 컴파일한 결과가 여러 자바 선언과 대응 하는 경우가 있다.
이때 코틀린 선언과 대응하는 자바선언에 각각 애노테이션을 붙여야 할 때가 있다.
예) 코틀린의 프로퍼티는 자바의 필드+겟터/셋터 메소드와 대응한다.
주 생성자에서 프로퍼티를 선언하면 이런 접근자메소드와 파라미터 외에 자바 생성자 파라미터와 대응된다.
-> 애노테이션을 붙일 때 이런 요소중 어떤 요소에 애노테이션을 붙일지 표시할 필요가 있다.
사용 지점 대상 @ 사용지점대상: 이름 형태
예 Junit은 각 테스트 메소드 앞에 메소드를 실행시키는 조건이 있다.
TemporaryFolder라는 규칙을 사용하면 메소드가 끝나면 삭제될 임시 파일과 폴더를 만들 수 있다.
@get: Rule --->@Rule을 getter에 적용시켜라
만약 folder에 @Rule을 적용하면 일반적으로 코틀린 필드는 비공개라 오류가 발생한다.
"The @Rule ''folder" must be public"
class HasTempFolder{
@get:Rule // folder의 getter에 붙는다.
val folder = TemporaryFolder()
@Test
fun testUsingTempFolder() {
val createFile = folder.newFile("myfile.txt")
val createFolder = folder.newFolder("subfolder")
}
}
자바에 선언된 애노테이션을 사용해 프로퍼티(필드+get/set)에 애노테이션을 붙이면 일반적으로 프로퍼티의 필드에 붙는다.
코틀린으로 애노테이션을 선언하면 프로퍼티(필드+get/set)에 직접 적용할 수는 있는 애노테이션을 만들수있다.
property - 프로퍼티 전체 (자바에서 선언된 애노테이션 이 사용지점대상 사용못함)
field - 프로퍼티의 백킹필드
get - 프로퍼티 겟터
set - 프로퍼티 셋터
receiver - 확장함수 또는 프로퍼티의 수신 객체 파라미터
param - 생성자 파라미터
setparam - 셋터 파라미터
delegate - 위임 프로퍼티의 위임 인스턴스를 담아둔 필드
file - 파일 내의 최상위 함수와 프로퍼티를 담아둔 클래스.
* @file:JvmName("StringFunctions") 처럼 이름 설정.
자바와 달리 코틀린에서는 애노테이션 인자로 클래스나 함수선언이나 타입 외에 임의 식을 허용해준다.
예) @Suppress 애노테이션이다. 안전하지 못한 캐스팅의 경고를 무시하는 로컬변수 선언.
fun test(list: List<*>){
@Suppress("UNCHECKED_CAST")
val strings = list as List<String>
}
***자바 API를 애노테이션으로 제어하기!
코틀린은 코틀린으로 선언한 내용을 자바 바이트코드로 컴파일 하는 방법
코틀린 선언을 자바에 노출하는 방법을 제어하기 위한 애노테이션을 제공한다.
@JvmName --> 코틀린 선언의 자바 필드 메소드 이름을 변경
@JvmStatic --> 메소드, 객체 선언(object { } ), 동반객체(companion object)에 적용하면 그 요소가 자바에서 정적메소드로 이용가능.
@JvmOverloads --> 디폴트 파라미터 값이 있는 함수에 대해 컴파일러가 자동으로 오버로딩 함수 생성.
@JvmField --> 프로퍼티에 사용하면 게터 세터가 없는 public 자바 필드로 프로퍼티를 노출시킨다.
애노테이션을 활용한 JSON 직렬화 제어
직렬화(Serialization) - 객체를 저장장치, 또는 네트워크 통한 전송을 위해 텍스트나 이진 형식으로 변환하는 것이다.
역직렬화는 반대 과정으로 텍스트나 이진형태의 데이터를 원래 객체를 만들어 내는것.
data class Person(val name: String, val age: Int)
fun main() {
val person = Person("Alice", 29)
println(serialize(person))
// {"age": 29, "name": "Alice"}
val json = """{"name":"Alice", "age":29}"""
println(deserialize<Person>(json))
// Person(name=Alice, age=29)
JSON에는 객체의 타입이 저장되지 않기 때문에 JSON 데이터로부터 인스턴스를 만들려면,
타입인자로 클래스를 명시해준다!
원시및 String타입만 직렬화 하는 클래스에 안에 들어있지만, 실제로는 다른 값 객체 클래스나 여러 값으로 이루어진 컬렉션 탕ㅂ의 프로퍼티도 들어갈수있다.
애노테이션을 이용해 제어해보기
1. 기본적으로 모든 프로퍼티를 직렬화 시킴.
2. 키 값은 프로퍼티 이름으로함.
@JsonExclude -> 직렬화 및 역직렬화에 그 프로퍼티를 무시한다.
@JsonName -> 키로 쓰이는 프로퍼티 일므 대신 애노테이션이 지정한 이름을 사용.
data class Person(
@JsonName("alias") val name: String,
@JsonExclude val age: Int)
'Kotlin in Action > 코틀린 답게 사용하기' 카테고리의 다른 글
애노테이션 만들기 (0) | 2021.03.05 |
---|---|
스타 프로젝션 (0) | 2021.03.04 |
사용 지점 변성: 타입이 언급되는 지점에서 변성지정 (0) | 2021.03.03 |
반공변성: 뒤집힌 하위 타입 관계 (0) | 2021.03.02 |
변성: 제네릭과 하위 타입2 (0) | 2021.03.02 |