[Kotlin] Data class

YounDitt·2020년 9월 27일
0

[Kotlin] 기본

목록 보기
2/3

데이터를 보관/관리하는 클래스이다.

1. 장점

  • toString(), hashCode(), equals(), copy(), componentN functions 메소드를 자동으로 만들어준다.

2. 특징

  • 생성자에는 1개 이상의 프로퍼티를 선언되어야 한다.
  • 생성자의 프로퍼티는 val 또는 var로 선언되어야 한다.
  • 데이터클래스에 abstract, open, inner를 붙일 수 없다.
  • 상속받을 수 없다.(final)

Properties Declared in the Class Body

data class Person(val name: String) { var age: Int = 0 }

생성자 안에 정의된 properties만 사용하여 자동생성된다. 내부선언된 변수는 달라도 생성자 안에 선언된 값만 같으면 같은 것으로 취급된다(==)

3. 메소드

생성자에 정의된 프로퍼티를 기준으로 자동생성된다.

1. toString()

  • 객체의 주소(Java)가 아닌 생성자에 정의된 프로퍼티를 선언순서대로 문자열로 표현
    (지역변수 x)

2. hashCode()

  • 인스턴스의 숫자표현으로 객체의 참조값

3. equals()

  • 객체의 동질성(동등성)을 비교(hashCode로 비교)
  • equals를 정의했다면, 반드시 hashCode도 재정의해야한다. (Java 기준 포스팅)

    👀 Kotlin 의 '==' 와 Java의 '=='

//java
int a = 10;
int b = 10;
//String pool 을 사용하지 않기 위해
String A = new String("10");
String B = new String("10");
//kotlin
val a:Int = 10
val b:Int = 10
//String pool 을 사용하지 않기 위해
val A:String = String(StringBuilder("10"))
val B:String = String(StringBuilder("10"))

  • Kotlin의 ==는 내부적으로 equals를 호출하는 방식으로 컴파일 된다.

4. copy()

  • 객체의 복사본을 만들어 리턴한다.(얕은복사)
  • 인자로 생성자에 정의된 프로퍼티를 넘길 수 있으며, 그 프로퍼티의 값이 변경된 객체가 복사, 생성된다.
  • HashMap등의 컨테이너에 데이터클래스 객체를 담는 경우 반드시 Immutable해야한다.(val)
    copy()를 이용하여 원본과 다른 생명주기를 갖는 불변한 복사본을 만들어 낸다.

👀 얕은복사(swallow copy)와 깊은복사(depp copy)

  • 얕은 복사

    • 객체를 복사할때, 해당 객체만 복사하여 새 객체를 생성한다.
    • 복사된 객체의 인스턴스 변수는 원본객체의 인스턴스 변수와 같은 메모리 주소를 참조한다.
    • 따라서, 해당 메모리주소의 값이 변경되면 원본객체 및 복사객체의 인스턴스값은 같이 변경된다.
  • 깊은 복사

    • 객체를 복사할때, 해당객체와 인스턴스변수까지 복사한다.

    • 전부를 복사하여 새 주소에 담기 때문에 참조를 공유하지 않는다.

    • Java에서 clone을 할 경우

      List<String> list = new ArrayList<>();
      
      List<String> newList = list; //얕은복사
      
      List<String> newList = (ArrayList<>())list.clone() //깊은복사;
      newList.addAll(list); //깊은복사

      단, ArrayList의 Item으로 객체가 선언되어 있다면 깊은복사시에도 데이터가 유지된다.
      👀 객체의 깊은 복사

    1. 객체의 복사생성자를 추가한다.
      public MyObject(){} //기본 생성자
      public MyObject(MyObject obj){ //복사 생성자
      this.title = obj.getTitle();
      }
    2. 각 Item의 객체에 깊은복사를 수행한다.
      for(MyObject item : list){
        newList.add(new MyObject(item));
      }

5. Component N functions

Destructuring Declarations
선언 순서대로 각 프로퍼티에 해당하는 작업을 한다.

//Kotlin
data class Car(val tire:String, val oil:String)
fun main(){
  val myCar = Car("circle", "gasoline")
  // 일반적인 방법
  val tire = myCar.tire
  val oil = myCar.oil
  
  // Destructuring Declarations
  val (tire, oil) = myCar
}

// kotlin to JAVA decompile
   public final String component1() {
      return this.tire;
   }
   public final String component2() {
      return this.oil;
   }
  • 컴파일 시점에서 componeneN() 메소드들을 자동으로 생성하며, 생성자에 정의된 프로퍼티 순서대로 대입한다.

클래스 위임

  • 코틀린의 함수는 기본적으로 final이다.(상속불가)
  • 클래스 기능의 일부를 재구현 하는 클래스를 만들때 by(데코레이터 패턴)를 사용한다.
  • 새로운 클래스는 기존 클래스의 구현방식에 대해 의존관계가 생기지 않는다

👀 데코레이터 패턴(decorator pattern)
상속을 허용하지 않는 기존 클래스 대신 사용할 수 있는 새로운 클래스(데코레이터)를 만들되, 기존 클래스와 같은 인터페이스를 데코레이터가 제공하게 만들고, 기존 클래스를 데코레이터 내부에 필드로 유지하는 것.

새로 정의하는 기능은 데코레이터의 메소드에 새로 정의하고 기존 기능이 그대로 필요한 부분은 데코레이터의 메소드가 기존 클래스의 메소드에게 요청을 전달(forwarding)한다.

영속화 관련 참고
클래스위임 참고
참고 1
참고 2

profile
Hello, Android

1개의 댓글

comment-user-thumbnail
2020년 10월 27일

안녕하세요! copy() 메소드는 내부적으로 새로운 객체를 생성해서 반환하기 때문에 깊은 복사가 아닐까 싶네요!

답글 달기