이 글은 Kotlin In Action을 참고 하였습니다.
더욱 자세한 설명이나 예제는 직접 책을 구매하여 확인 하시기 바랍니다
자바의 클래스는 toString, equals, hashCode를 반드시 오버라이드 해야 합니다.
코틀린에서는 이를 자동으로 컴파일러에서 해줍니다. (따로 만드는 수고스러움을 덜수 있습니다~)
4.3.1 클래스의 기본 method 구현
class Client(val name: String, val postalCode: Int) {
override fun toString() = "Client(name=$name, postalCode=$postalCode)"
}
fun main(args: Array) {
val client1 = Client("Alice", 342562)
println(client1)
}
자바는 기본적으로 Client의 toString()을 구현해 줍니다.
다만 print 했을때 Client@d97g8cs 란 쓸모없는 값을 리턴해 줍니다.
따라서 위 코트처럼 override하여 유요향 정보를 출력하도록 toString()을 재정의 할 수 있습니다.
class Client(val name: String, val postalCode: Int)
fun main(args: Array) {
val client1 = Client("Alice", 342562)
val client2 = Client("Alice", 342562)
println(client1 == client2)
}
코틀린에서 == 는 자바에서 equals와 같습니다.
따라서 두개의 결과로 true가 나와야 하지만 false가 나옵니다.
true로 반환값을 만들기 위해서는 equals()도 override해야 합니다.
class Client(val name: String, val postalCode: Int) {
override fun equals(other: Any?): Boolean {
if (other == null || other !is Client)
return false
return name == other.name &&
postalCode == other.postalCode
}
override fun toString() = "Client(name=$name, postalCode=$postalCode)"
}
fun main(args: Array) {
val processed = hashSetOf(Client("Alice", 342562))
println(processed.contains(Client("Alice", 342562)))
}
각 property를 비교하도록 equals를 수정했습니다.
따라서 이제 client1 == client2는 true가 나옵니다. (equals를 override 했으니, == 연산시 override된 함수를 사용합니다.)
단!! main 함수를 실행시키면 hasSet에 해당 객체가 없다면 false를 반환합니다.
이는 hashcode가 없기 때문입니다. 따라서 equals를 override한다면 hashcode도 반드시 override 해야 합니다.
이는 "JVM의 언어에서는 equals()가 true인 객체는 반드시 hashcode() 값도 동일해야 한다"는 제약이 있기 때문입니다.
hashSet은 객체를 찾을때 먼저 hashcode를 이용하여 찾습니다. 그리고 나서 hashcode가 같은게 여러개 존재 한다면 그때서야 값을 비교합니다.
위 코드에서는 두 객체의 hashcode가 다르니, contains에서 false가 떨어집니다.
override fun hashCode() : Int = name.hashCode() * 31 + postalCode
따라서 위와같이 hashCode()도 override해야만 비교시 정상 동작합니다.
4.3.2 data class
data class Client(val name: String, val postalCode: Int)
fun main(args: Array) {
val bob = Client("Bob", 973293)
println(bob.copy(postalCode = 382555))
}
참 쉽죠잉.
class 앞에 data 키워드만 붙이면 됩니다.
이런게 data로 선언된 Client는 클래스는 컴파일시에 아래작업이 추가적으로 수행됩니다.
- 인스턴스간 비교를 위한 equals() 자동생성
- Hash 기반 container에서 키로 사용할 수 있도록 hashCode() 자동 생성
- property 순서대로 값을 반환해 주는 toString() 자동생성
이때 위엔 언급된 함수들은 주 생성자(main constructor)에 주어진 값들을 기반으로 만들어집니다.
(보조 생성자나 기타 선언된 property들은 조합요소가 아닙니다.)
data 클래스이 이외에도 copy()를 제공합니다.
이는 data 클래스를 불변클래스로 만들면서 일부 값이 변경되어야 할때 기존 값들을 복사하여 새 객체를 만들어주는 역할을 합니다.
4.3.3 class delegation: by
class CountingSet(val innerSet: MutableCollection = HashSet()) : MutableCollection by innerSet {
var objectsAdded = 0
override fun add(element: T): Boolean {
objectsAdded++
return innerSet.add(element)
}
override fun addAll(c: Collection): Boolean {
objectsAdded += c.size
return innerSet.addAll(c)
}
}
fun main(args: Array) {
val cset = CountingSet()
cset.addAll(listOf(1, 1, 2))
println("${cset.objectsAdded} objects were added, ${cset.size} remain")
}
위 CountingSet 함수는 MutableCollection을 상속받으나, innerSet에 해당 구현을 위임 합니다.
따라서 추가작업이 필요하여 override되어 구현된 add()나 addAll() 이외의 다른 API들은 기본 HashSet() class의 API를 사용합니다.
'개발이야기 > Kotlin' 카테고리의 다른 글
[Kotlin] 코틀린 람다 #1 - 기본 문법 (5) | 2018.04.25 |
---|---|
[Kotlin] 코틀린 object (6) | 2018.04.23 |
[Kotlin] 코틀린 class 생성자와 property (0) | 2018.04.20 |
[Kotlin] 코틀린 삼중따옴표, 정규식, 문자열, 중첩함수 , 확장함수 (2) | 2018.04.18 |
[Kotlin] 코틀린 확장함수와 프로퍼티, 가변인자, 중위함수 (0) | 2018.04.16 |