[Kotlin] 동등성

최율·2022년 12월 9일

Kotlin

목록 보기
6/10

Class의 동등성

다음의 코틀린 코드가 있을 때, 결과값을 예상해보자.

class Person(val firstName: String, val lastName:String, val age: Int) {}

fun main() {
	val person1 = Person("James", "Bond", 40)
    val person2 = Person("James", "Bond", 40)
    
    println(person1 == person2)
}

결과는 false이다. 왜 그럴까?
person1과 person2의 내용인 firstName, lastName, age가 모두 같지만 두 변수는 결국 다른 인스턴스를 가리키고 있기 때문이다.

만약 프로그래머가 Person 객체의 이름과 나이가 같다면 같은 객체라고 새롭게 정의하고 싶다면 equals() 와 hashCode() 함수를 override 해야한다.

그렇다면 equals()를 재정의하여 원하는대로 프로그램이 작동하게 만들어보자.

class Person(val firstName: String,
             val familyName: String,
             val age: Int) {
    override fun equals(other: Any?): Boolean {
        if (other !is Person) return false // 타입 비교
        else {
            return this.firstName == other.firstName && this.familyName == other.familyName && this.age == other.age
        }
    }
}

치밀하고 체계적이여서 빈틈이 없는 코드를 작성할 수 있지만 번거로운 것은 사실이다.

그런 번거로움을 덜어주는 것이 바로 data class 이다.

Data Class

data class Person(val firstName: String, val lastName: String, val age: Int)

data 키워드를 붙여주면 자동으로 equals()와 hashCode()가 재정의되어 번거로움이 줄어든다. 단, 비교는 주생성자의 파라미터의 비교로 하기 때문에 그 점을 유의해야한다.

위와 같이 작성할 경우 toString() 메서드까지 지원해주는데 한번 확인해보자.

fun main() {
	val person = Person("James", "Bond", 40)
    println(person.toString()) //Person(firstName=James, familyName=Bond, age=40)
}

Data Class 의 메서드

data class의 메서드로 copy() 메서드가 존재한다.
data class의 프로퍼티를 그대로 복사하여 새로운 인스턴스를 만든다.
물론 data class이기 때문에 둘의 동등성은 같다고 보장된다.

fun main() {
    val person = Person("James", "Bond", 40)
    println(person.toString())

    person.show()
    person.copy().show()
    person.copy(firstName = "John").show()
    person.copy(firstName = "Trevor", familyName = "Phillips", age = 45).show()
}

Pair & Triple

코틀린에서 기본적으로 지원하는 Pair와 Triple 데이터 클래스를 알아보자.

fun main() {
	val pair = Pair(1, "two") // val pair = 1 to "two" 로 대체 가능
	
    println(pair.first + 1) // 2
	println("${pair.second} !") // two !
	
    val triple = Triple("one", 2, false)
	
    println("${triple.first} !") // one !
	println(triple.second – 1) // 1
	println(!triple.third) // true
}

구조 분해 선언

data class Person(val firstName: String, val familyName: String, val age: Int)

fun main() {
	val person = Person("John", "Doe", 25)
    val (firstName, familyName, age) = person
    
    // firstName, familyName, age 를 한번에 선언하였다.
    
    if (age < 18) {
    	println("age is $age")
    }
    
    val (_, familyName2, age2) = person
    
    // firstName을 생략하고 싶다면 언더바(_)를 활용하면 된다.
    
    val (firstName3, familyName3) = person
    
    // age를 생략하고 싶다면 변수의 선언을 생략하면 된다.
}

그럼 이 선언 방식을 어떻게 써먹을 수 있을까?

파이썬에서 enumerate 함수와 튜플의 조합을 생각해보자.

for (name, value) in enumerate(my_dictionary):
	# do something...
    pass

위 코드처럼 코틀린에서 활용가능하다.


val cities = arrayOf( Pair("Paris", "France"), Pair("Seoul", "Korea") )

fun main() {
	for ((city, country) in cities) {
		println("city: $city, country: $country")
	}
}
profile
공부한 것을 기록하고 공유하는 학생입니다!

0개의 댓글