7. 연산자 오버로딩과 기타 관례
- 언어 기능을 타입에 의존하는 자바와 달리 코틀린은 관례에 의존합니다.
#
7.1 산술 연산자 오버로딩#
7.1.1. 이항 산술 연산 오버로딩- 오버로딩 가능한 이항 산술 연산자는 다음과 같습니다.
식 | 함수 이름 |
---|---|
a * b | times |
a / b | div |
a % b | mod(1.1 부터 rem) |
a + b | plus |
a - b | minus |
코틀린 연산자를 자바에서 호출하기는 쉽습니다.
- 코틀린 연산자는 자동으로 교환 법칙(commutativity)를 지원하지는 않습니다.
- 연산자 함수의 반환 타입이 꼭 두 피연산자 중 하나와 일치해야하지만은 않습니다.
#
7.1.2. 복합 대입 연산자 오버로딩+=
,-=
등의 연산자는 복합 대입(compound assignment) 연산자라고 부릅니다.
- 복합 대입 연산자 함수도 비슷하게
minusAssign, timesAssign
등의 이름을 사용합니다.
a += b
는a = a.plus(b)
또는a.plusAssign(b)
로 번역할 수 있습니다.
#
7.1.3. 단항 연산자 오버로딩- 코틀린은 단항 연산자도 제공합니다.
- 오버로딩할 수 있는 단항 산술 연산자는 다음과 같습니다.
식 | 함수 이름 |
---|---|
+a | unaryPlus |
-a | unaryMinus |
!a | not |
++a, a++ | inc |
--a, a-- | dec |
#
7.2 비교 연산자 오버로딩- 코틀린은 자바와 달리 모든 객체에 대해 비교 연산을 수행할 수 있습니다.
#
7.2.1. 동등성 연산자: equals- 코틀린은
==
연산자를equals
메서드 호출로 컴파일합니다. a == b
는a?.equals(b) ?: (b == null)
을 의미합니다.- 식별자 비교(identity equals,
===
) 를 사용해 파라미터의 수신 객체와 같은 지 비교하며, 자바의==
연산자와 동일합니다.
#
7.2.2. 순서 연산자: compareTo- 코틀린도 자바와 동일한
Compareable
인터페이스를 지원합니다. a >= b
는a.compareTo(b) >= 0
을 의미합니다.- 다음과 같은 라이브러리도 사용가능합니다.
#
7.3 컬렉션과 범위에 대해 쓸 수 있는 관례#
7.3.1. 인덱스로 원소에 접근: get과 set- 코틀린에서 맵의 원사에 접근할 때나 자바에서 배열 원소에 접근할 때,
[]
를 사용합니다. x[a, b]
는x.get(a, b)
로 호출됩니다.x[a, b] = c
는x.set(a, b, c)
로 호출됩니다.
#
7.3.2. in 관례- 컬렉션이 지원하는 다른 연산자는
in
이 있습니다. a in c
는c.contains(a)
로 전달됩니다.
#
7.3.3. rangeTo 관례start..end
는start.rangeTo(end)
를 지원합니다.rangeTo
함수는 범위를 반환합니다.
#
7.3.4. for 루프를 위한 iterator 관례- 코틀린의
for
루프는 범위 검사와 똑같이in
연산자를 사용하나 의미는 다르며 이때는list.iterator()
를 호출합니다.
#
7.4 구조 분해 선언과 component 함수- 코틀린의 특징 중 구조 분해 선언(destructuring declaration) 에 대해 이야기합니다.
val (a, b) = p
는val a = p.component1(), val b = p.component2()
와 같습니다.- 다음과 같이 사용할 수 있습니다.
#
7.4.1. 구조 분해 선언과 루프- 확장 함수를 대표적으로 사용한 예제는 다음과 같습니다.
#
7.5 프로퍼티 접근자 로직 재활용: 위임 프로퍼티- 위임 프로퍼티(delegated property) 를 사용하면 값을 뒷받침하는 필드에 단순히 저장하는 것보다 더 복잡한 방식으로 작동하는 프로퍼티를 쉽게 구현할 수 있습니다.
- 이러한 특성의 기반에는 위임이 있으며, 위임은 객체가 직접 작업을수행하지 않고 다른 도우미 객체가 그 작업을 처리하게 맡기는 디자인 패턴입니다.
- 작업을 처리하는 도무이 객체를 위임 객체(delegate) 라 부릅니다.
#
7.5.1. 위임 프로퍼티 소개- 일반적인 위임의 문법은 다음과 같습니다.
- 프로퍼티 위임 관례를 따르는 Delegate 클래스는
getValue
와setValue
를 제공해야합니다.
#
7.5.2. 위임 프로퍼티 사용: by lazy()를 사용한 프로퍼티 초기화 지연- 지연 초기화(lazy initialization) 는 객체의 일부분을 초기화하지 않고 남겨뒀다가 실제로 그 부분의 값이 필요할 경우 초기화할 때 흔히 쓰이는 패턴입니다.
- 초기화 과정에 자원을 많이 사용하거나 객체를 사용할 때마다 꼭 초기화하지 않아도 되는프로퍼티에 대해 지연 초기화 패턴을 사용할 수 있습니다.
- 위의 예제는 뒷받침하는 프로퍼티(backing property) 라는 기법을 사용합니다.
_emails
라는 프로퍼티는 값을 저장하고, 다른 프로퍼티인emails
는_emails
라는 프로퍼티에 대한 읽기 연산을 저장합니다.
- 코틀린은 이를 개선했으며,
lazy
라는 표준 라이브러리 함수가 있습니다.
#
7.5.3. 위임 프로퍼티 구현- 코틀린의 위임 방식에 대한 예제는 다음과 같습니다.
by
오른쪽에 오는 객체를 위임 객체(delegate) 라고 부릅니다.- 코틀린은 위임 객체를 감춰진 프로퍼티에 저장하고, 주 객체의 프로퍼티를 읽거나 쓸 때마다 위임 객체의
getValue
와setValue
를 호출해줍니다.
- 위임 메커니즘을 모든 타입에 두루두루 사용할 수 있습니다.
#
7.5.4. 위임 프로퍼티 컴파일 규칙- 컴파일러는 모든 프로퍼티 접근자 안은
getValue
와setValue
호출을 생성해줍니다.val x = c.prop
는val x = <delegate>.getValue(c, <property>)
c.prop = x
는<delegate>.setValue(c, <property>, x)
#
7.5.5. 프로퍼티 값을 맵에 저장- 자신의 프로퍼티를 동적으로 정의할 수 있는 객체를 만들 때 위임 프로퍼티를 활용하는 경우가 있으며 그런 객체를 확장 가능한 객체(expando object) 라고 합니다.
- 표준 라이브러리가
Map
과MutableMap
인터페이스에 대해getValue
와setValue
확장 함수를 제공합니다.
#
7.5.6. 프레임워크에서 위임 프로퍼티 활용User
의 상위 클래스인Entity
클래스는 데이터베이스 칼럼을 엔티티의 속성(attribute) 값으로 연결해주는 매핑이 있습니다.
#
7.6 요약- 코틀린에서는 정해진 이름의 함수를 오버로딩암으로써 표준 수학 연산자를 오버로딩할 수 있습니다.
- 비교 연산자는
equals
와compareTo
메서드로 변환됩니다. - 클래스에
get, set, contains
라는 함수를 정의하면 그 클래스의 인스턴스에 대해[]
와in
연산을 사용할 수 있고, 그 객체를 코틀린 컬렉션 객 체와 비슷하게 다룰 수 있습니다. - 미리 정해진 관례를 따라
rangeTo, iterator
함수를 정의하면 범위를 만들거나 컬렉션과 배열의 원소를 이터레이션할 수 있습니다. - 구조 분해 선언을 통해 한 객체의 상태를 분해해서 여러 변수에 대입할 수 있습니다.
- 위임 프로퍼티를 통해 프로퍼티 값을 저장하거나 초기화하거나 읽거나 변경할 때 사용하는 로직을 재활용할 수 있습니다. 위임 프로퍼티는 프레임워크를 만들 때 아주 유용합니다.
- 표준 라이브러리 함수인
lazy
를 통해 지연 초기화 프로퍼티를 쉽게 구현할 수 있습니다. Delegates.observable
함수를 사용하면 프로퍼티 변경을 관찰할 수 있는 관찰자를 쉽게 추가할 수 있습니다.- 맵을 위임 객체로 사용하는 위임 프로퍼티를 통해 다양한 속성을 제공하는 객체를 유연하게 다룰 수 있습니다.