kotlin - data class의 copy

조갱·2022년 8월 14일
2

kotlin

목록 보기
9/12

kotlin의 data class는 편리한 기능을 제공한다.

아래왜 같은 메소드를 자동으로 생성해줌으로써,
개발자는 더이상 자바에서처럼 개별적으로 만들 필요가 없어졌다.

  • toString()
  • hashCode()
  • equals()
  • copy()

그와중에, copy()에 대해 주의해야 할 점에 대해 소개하고자 한다.

kotlin -> java 코드 변환

변환 방법 : 여기를 클릭

data class TestModel(
    val name: String,
    val age: Int,
    val address: Address,
)

data class Address(
    var addr1: String,
    var addr2: String,
    var addr3: String
)

위 data class를 java로 변환하면 아래와 같은 java 코드가 있다.

@NotNull
public final TestModel copy(@NotNull String name, int age, @NotNull Address address) {
	Intrinsics.checkNotNullParameter(name, "name");
    Intrinsics.checkNotNullParameter(address, "address");
    return new TestModel(name, age, address);
}

Shallow Copy

위 코드에서 볼 수 있듯, 변환된 copy 메소드는 단순히 address파라미터를 받아서 새로운 객체에 넣어만 준다.
이 말은, address객체는 얕은 복사(shallow copy)가 되며 원본의 address값이 바뀌면 복사본의 address도 바뀐다는 얘기다.

Example

예시로 확인해보자. 테스트 시나리오는 아래와 같다.


나는 경기도 수원시에 거주하는 김이름이다.
우리 가족은 엄마, 아빠, 나까지 3명이다.

같이 오순도순 살고있는 도중, 나'만' 출가하여 안양시에 자리를 잡았다.

    @Test
    fun addrTest() {
        val me = TestModel(
            name = "김이름",
            age = 27,
            address = Address(
                addr1 = "대한민국",
                addr2 = "경기도",
                addr3 = "수원시"
            )
        )
        val mother = me.copy(name = "김엄마", age = 50)
        val father = me.copy(name = "김아빠", age = 53)

        println(mother)

        me.address.addr3 = "안양시"

        println(mother)
    }
TestModel(name=김엄마, age=50, address=Address(addr1=대한민국, addr2=경기도, addr3=수원시))
TestModel(name=김엄마, age=50, address=Address(addr1=대한민국, addr2=경기도, addr3=안양시))
BUILD SUCCESSFUL in 5s

나만 안양시로 이사했는데, 엄마까지 덩달아 이사당해(?)버렸다.

Solution

deepCopy 메소드를 만들자.

data class TestModel(
    val name: String,
    val age: Int,
    val address: Address,
) {
    fun deepCopy(name: String? = null, age: Int? = null, address: Address? = null): TestModel {
        return TestModel(
            name = name ?: this.name,
            age = age ?: this.age,
            address = address?.copy() ?: this.address.copy()
        )
    }
}

그리고 테스트 코드도 deepCopy로 수정

    @Test
    fun addrTest() {
        val me = TestModel(
            name = "김이름",
            age = 27,
            address = Address(
                addr1 = "대한민국",
                addr2 = "경기도",
                addr3 = "수원시"
            )
        )
        val mother = me.deepCopy(name = "김엄마", age = 50)
        val father = me.deepCopy(name = "김아빠", age = 53)

        println(mother)

        me.address.addr3 = "안양시"

        println(mother)
    }
TestModel(name=김엄마, age=50, address=Address(addr1=대한민국, addr2=경기도, addr3=수원시))
TestModel(name=김엄마, age=50, address=Address(addr1=대한민국, addr2=경기도, addr3=수원시))
BUILD SUCCESSFUL in 7s

이제 엄마는 수원에 무사히(?) 잘 계실 것이다.

profile
A fast learner.

0개의 댓글