아래의 글은 드미트리 제메로프, 스베트라나 이사코바 저/오현석역,『Kotlin in Action』,에이콘출판사(2017)의 내용을 기반으로 작성하였습니다.
자바 : 언어 기능을 타입에 의존하는 관례
코틀린 : 함수 이름에 의존하는 관례
자바 : + : primative type에서 사용, String : String concat 연산
코틀린 : + : plus란 이름으로 된 연산자 + 로 대체됨, operator 키워드 붙이면 됨, 확장함수로도 정의 가능
* 관례로 쓰는 이름을 붙였는데, operator 연산자가 없으면 operator modifier is required 라고 에러
a + b - > a.plus(b) 가 됨
교환 법칙이 성립이 안됨 예를 들어 p * 1.5와 1.5 * p는 다름, p.times가 있냐와 Double.times가 있냐의 차이
오버로딩 가능한 이항 산술 연산자
expression | operator convention |
a * b | times |
a / b | div |
a % b | mod (1.1 rem) |
a + b | plus |
a - b | minus |
data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}
}
>>> val p1 = Point(1, 1)
>>> val p2 = Point(2, 3)
>>> println(p1 + p2)
Point(x = 3, y = 4)
operator fun Point.plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}
비트연산자
operator convention | 정의 | 자바 |
shl | 왼쪽 시프트 | << |
shr | 오른쪽 시프트 | >> |
ushr | 오른쪽 시프트 0 부호 비트 | >>> |
and | 곱 | & |
or | 합 | | |
xor | 배타 | ^ |
inv | 반전 | ~ |
복합대입연산자
expression | operator convention |
+= | plusAssign |
-= | minusAssign |
*= | timesAssign |
/= | remAssign |
단항연산자오버로딩
expression | operator convention |
+a | unaryPlus |
-a | unaryMinus |
!a | not |
++a, a++ | inc |
--a, a-- | dec |
operator fun BigDecimal.inc() = this + BigDecimal.ONE
>>> val num = BigDecimal.ZERO
>>> println(num++)
0
>>> println(num)
1
>>> println(++num)
2
비교연산자
expression | java |
== | equals |
=== | == |
!= | !equals |
< | p1.compareTo(p2) < 0 |
> | p1.compareTo(p2) > 0 |
<= | p1.compareTo(p2) <= 0 |
>= | p1.compareTo(p2) >= 0 |
Comparable에 compareTo가 operator가 붙어 있어서 하위에서는 붙일 필요가 없다.
Comparable 인터페이스를 구현하는 모든 자바 클래스는 코틀린에서 간결한 연산자 구문으로 비교 가능
컬렉션
expression | operator convention |
val x = map[0] | get |
map[1] = 42 | set |
in | contains |
... | rangeTo |
for (x in list) { ... } | iterator |
val now = LocalDate.now()
val vacation = now...now.plusDays(10)
>>> println(now.plusWeeks(1) in vacation)
true
operator fun CharSequence.iterator(): CharInterator: Interator
>> for(c in "abc") {}
operator fun ClosedRange<LocalDate>.iterator(): Interator<LocalDate> =
object : Iterator<LocalDate> {
val current = start
override fun hasNext() = current <= endInclusive
override fun next() = current.apply {
currnet = plusDays(1)
}
}
>>> val newYear = LocalDate.ofYearDay(2017, 1)
>>> val daysOff = newYear.minusDays(1)..newYear
>>> for (dayOff in dayOff) { println(dayOff) }
2016-12-31
2017-01-01
구조분해선언 : componentN 함수
val (a, b) = p > val a = p.component1() val b = p.component2()
* data 클래스는 componentN 함수를 자동으로 만들어 준다. 코틀린 표준 라이브러리는 맨앞의 5개 원소에 대한 componentN을 제공
data class NameComponents(val name: String, val extention: String)
fun splitNameExt(filename: String): NameCompoents {
val result = filename.split('.', limit = 2)
return NameComponents(result[0], result[1])
}
>>> val (name, ext) = splitNameExt("file.txt")
>> println(name)
file
>>> println(ext)
txt
fun splitNameExt2(filename: String): Namecomponents {
var (name, extention) = file.split('.', limit = 2)
return NameComponents(name, extention)
}
for (entry in map.entries) {
val key = entry.component1()
val value = entry.compoent2()
}
위임프로퍼티 : 연산 위임
class Delegate {
operator fun getValue(...) { ... }
operator fun setValue(..., value: Type) { ... }
}
class Foo {
var p: Type by Delegate()
}
>>> var foo = Foo()
>>> var oldValue = foo.p // delete.getValue 호출
>>> foo.p = newValue // delete.setValue 호출
backing 프로퍼티 : lazy지원, lazy다음에 로딩할 인자는 람다
class Person(val name: String) {
val email by lazy { loadEmails(this) }
}
위임프로퍼티 실제 구현 : 연산 수행 값 get, set 만으로도 특정 메소드 get set이 되도록 위임가능하고 위임안에서 다른 작업도 수행 가능
open class PropertyChangeAware {
protected val changeSupport = PropertyChangeSupport(this)
fun addPropertyChangeListner(listener: PropertyChangeListenser) {
changeSupport.addPropertyChangeListener(listener)
}
fun removePropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.removePropertyChangeLisner(listener)
}
}
class ObservableProperty
(var propValue: Int, val changeSupport: PropertyChangeSupport) {
operator fun getValue(p: Person, prop: KProperty<*>): Int = propVAlue
operator fun setValue(p: Person, prop: KProperty<*>, newValue: Int) {
val oldValue = propValue
propValue = newValue
changeSupport.firePropertyChange(prop.name, oldValue, newValue)
}
}
class Person
(val name: String, age: Int salary: Int) {
} : PropertyChangeAware() {
private val observer = {
prop: KProperty<*>, oldValue: Int, newValue: Int ->
changeSupport.firePropertyChange(prop.name, oldValue, newValue)
}
var age: Int by ObservableProperty(age, changeSupport)
var salary: Int by ObservableProperty(salary, changeSupport)
}
val x = c.prop
// val x = <delegate>.getValue(c, <property>)
c.prop = x
// <delegate>setValue(c, <property>, x)
'독서관련 > Kotlin in Action' 카테고리의 다른 글
CH09 코틀린 제네릭스 (0) | 2021.01.29 |
---|---|
CH08 코틀린 고차함수 (0) | 2021.01.28 |
CH06 코틀린 컬렉션 및 배열 (0) | 2021.01.17 |
CH06 코틀린 primative 타입 (0) | 2021.01.11 |
CH06 코틀린 타입 시스템 (0) | 2021.01.10 |