[Kotlin] 동등성

최율·2022년 12월 9일
0

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이다. 왜 그럴까?
person1person2의 내용인 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

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

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개의 댓글