Operator overloading and other conventions
- 함수를 통해서 연산자 오버로딩
operator fun times
- 확장으로도 가능
operator fun Char.times(count: Int)
- Nullable 타입에 대해서도 적용 가능(equal 제외)
산술 연산자
- binary 연산자
- times, div, mod, plus, minus
- 비트연산자는 기호 없음
- coumpound assignment 연산자
- timesAssign, divAssign, modAssign, plusAssign, minusAssign
- unary 연산자
- unaryPlus, unaryMinus, not, inc, dec
- 전치, 후치 증감 연산(inc, dec) 정상적으로 진행됨
1 |
|
비교 연산자
- 동치 비교 연산자
a == b
를a?.equals(b) ?: (b == null)
로 연산함- null도 동치를 비교해야하기 때문
- 그러므로 equal은 nullable type에 대해서 적용 불가
- 레퍼런스를 비교하는
===
는 오버로딩 불가 - 오버로딩 시
override
를 써야함,Any
클래스에 이미 정의되어 있기 때문
- 순서 비교 연산자
- 비교가 가능하려면
Comparable
을 상속받아야함 a >= b
->a.compareTo(b) >= 0
- 위의 식은 Comparator의 정의를 기가막히게 보여주는 식이라고 생각함
- `co
- 비교가 가능하려면
1 |
|
기타 연산자 혹은 Convention 들
- 접근 연산자: get, set:
x[a, b] = c
->x.set(a, b, c)
- 포함 연산자: contains:
a in c
->c.contains(a)
- 범위 연산자: rangeTo:
start..end
->start.rangeTo(end)
- 순회 연산자: Iterator
- 인터페이스
Iterator
를 구현한 객체를 리턴해야 함 hasNext
,next
두 함수를 구현해야함
- 인터페이스
- 구조 분해 선언
component1
,component2
등을 선언해주어야 함- array나 collection, data class에는 이미 선언되어 있음
1 |
|
delegated properties
by
를 통해서 프로퍼티를 위임할 수 있음- 프로퍼티 산출이 복잡하거나, 가능하면 늦게 계산하고 싶다거나 할때 유용함
- 위임을 담당하는 객체는 복잡한 상태를 소유할수도 있음
- 프로퍼티 리스트를 map으로 보관하는 등의 응용도 가능
1 |
|
Higher-order functions
- HOF: 람다를 파라미터로 받거나 리턴
- Function Type:
(T, U) -> R
- 자체로 Null이 될수 있음
((T, U) -> R)?
- 인자로 받는 경우, 기본 인자를 람다로 줄 수 있다.
- 자체로 Null이 될수 있음
inline functions
- inline 함수
- 기존 다른 언어들에서와 의미가 같음
- 람다를 인자로 받으면 그 람다까지도 inline
noinline
을 붙이면 특정 람다는 인라인 시키지 않을 수 있음- inline된 람다에서는 외부 함수에 대한 리턴이 가능함
- inline과 generic
- generic과 함께 쓸 때 타입이 전달되지 않음 (함수이므로)
- 단 파라미터화 타입에
reified
를 붙일경우 inline시에 타입 전달됨
- inline과 최적화
- collection의
filter
함수 등은 인라인 되어서 성능 이득을 봄 - 코드 사이즈 증가에 대해 주의할 것
- collection의
- inline과 resource
- python의 with, java의 try-with-resource처럼 활용 가능
- 락을 잡고 풀어줘야할때 이를 인라인 안에 숨기고, 내부 로직만 집중 가능
1 |
|
HOF control flow
- labeled 리턴
- 람다에 대한 리턴인지, 외부 함수에 대한 리턴인지 라벨로 지정
- 라벨 안붙이고, 함수 이름으로도 가능
- 단 람다가 아니고 익명함수를 선언한 경우는 labeled 리턴 불가능함
1 |
|
Generics
- Java generic과 일맥상통
- 함수, 클래스, 인터페이스에 대해서 적용 가능
- Type parameter constraints
- 타입에 대한 upper bound를 정한다.
- Java
<T extends Number>
-><T : Number>
- 타입이 여러 인터페이스를 구현해야 할 경우는 where을 쓴다.
- 기본 upper bound는
Any?
이다.- 만약 non-null 타입을 원하면
Any
혹은 다른 non-null 타입을 지정한다.
- 만약 non-null 타입을 원하면
1 |
|
Generics at runtime
- Java와 같다. 문법적 설탕
- 런타임에는 모두 지워짐
- 일반적으로 불가:
value is List<String>
is
연산자로 제너릭 타입 체크 불가- 런타임에 지워지기 때문
- 다만 코틀린 컴파일러가 이미 Generic 내부 타입을 알 경우에는 사용 가능
- star projection
- 타입을 사용할 때 쓸 수 있음
- 대표적으로는
value is List<*>
- Java에서는
*
대신?
였음
- reified type
- inline 함수에서 Generic의 타입 정보를 보존함
- 실질적으로 runtime 체크가 아니다.
- 인라인 되었을 때에 가능한 수준에서 사용 가능
- typecast, check, reflection, type of argument로 사용 가능
- 객체 생성, 함수 정의에 사용 불가능
1 |
|
Declare-site variance
- covariant class/interface
Producer
out
으로 지정- generic 타입 T를 리턴에만 이용함
val
의 타입으로는 쓸 수 있음 (setter가 안생기므로)var
의 타입으로는 못씀 (setter는 인자를 입력 받으므로)List<Int>
는List<Number>
가 될 수 있다.List<Int>
의 모든 원소는Int
이므로Number
에 속한다.
- contravariant class/interface
Consumer
in
으로 지정- generic 타입 T를 인자의 타입에만 이용함
val
,var
둘다 못씀, 그냥 인자로 입력만 받아야함Comparable<Number>
는Comparable<Int>
가 될 수 있다.- Number를 비교할 줄 아는 객체는 Int도 비교할 줄 안다.
1 |
|
Use-site variance
out Type
: java의? extends Type
를 대체in Type
: java의? super Type
를 대체
1 |
|
Annotation
- 일단 자바에서와 맥락이 거의 같다
- 3가지 용도로 사용된다.
- compiler에 줄 정보를 기록
- Source code processing tools에 줄 정보를 기록
- 런타임에 app이 사용할 수 있도록 metadata를 기록
- use-site: 적용 대상을 특정
- Java 함수와 Kotlin 함수가 1:1 매칭이 되지 않기 때문
property
,field
,get
,set
등
- annotation 선언
- Java에서는
@interface
로 선언- 파라미터를 받는 것을 함수로 표현
- Kotlin에서는
annotation class
로 선언- 생성자 사용하듯 자연스럽게 쓰면 됨
- Java에서는
- meta annotation
- annotation class에 적용되는 annotation
- annotation parameter
- class의 경우
Person::class
처럼 바꿔서 인자로 사용 가능
- class의 경우
- reflection
- annotation이나 필드, 프로퍼티등을 런타임에 접근할 수 있음
1 |
|