데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      [Kotlin] DataClass와 Sealed Class 알아보기

      KIDO 24.05.02
      4,225 8 0
      DEVOTEE 요약
      데이터 클래스는 간단히 데이터를 저장하기 위한 객체를 만들 때 유용하며, toString(), equals(), hashCode(), copy()와 같은 메소드를 자동으로 제공하여 개발자의 부담을 줄여줍니다. 데이터 클래스는 상속이 불가능하며, 기본 생성자에는 최소 하나 이상의 파라미터가 필요하고, val 또는 var로 선언되어야 합니다. 데이터 클래스는 효율적으로 데이터를 다루기 위한 다양한 기능을 제공함으로써 반복적인 코드 작성을 줄여줍니다.
      DEVOTEE 추천 블로그

      Data Class

      • 프로그램을 작성하다 보면, 오직 데이터를 실어 나르기 위한 객체를 만들어할 때가 있다.

      • 이럴때 data class 를 사용하여 클래스를 생성하고, 데이터를 담을 수 있다.

      data class Person(val name: String, var age: Int)
      • 위와 같이 data class 로 선언한다.

      • Person은 데이터 클래스의 이름이다.

      • data class는 name과 age 라는 속성을 가진다.

      • 중요한 포인트는 data class는 copy(), equals(), hashCode(), toString() 에 대한 메소드를 자동으로 미리 구현되어 있다.

      • 개발자가 직접 메소드를 작성할 필요가 없다.


      Data class 에 필요한 필수 속성

      1. 기본 생성자는 무조건 1개 이상의 파라미터가 필요하다.

      2. 기본 생성자의 파라미터는 반드시 val(읽기 전용)이나 var(읽기-쓰기 가능) 를 가져야한다.

      3. 클래스는 open이 될수 없다. 즉, 상속이 불가능하다.

      4. abstract 도 될수 없다. 즉, 객체의 상속을 의도하지 않기 때문에 추상 클래스도 될 수 없다.

      5. inner이나 sealed 도 될수 없다.


      샘플코드

      • data class를 이제 만들어 보자.

      • 08.01.data_class_sample.kt 파일을 다음과 같이 작성하자.

      data class Person(val name: String, var age: Int)
      
      fun main(args: Array<String>) {
        val person01 = Person("UncleBae", 40)
        println(person01)
        println("Name: " + person01.name)
        println("Age: " + person01.age)
      }
      • 결과는 다음과 같다.

      Person(name=UncleBae, age=40)
      Name: UncleBae
      Age: 40
      • 자동으로 toString 메소드가 구현되어 있으므로 println로 객체자체를 출력할때 Person(name=UncleBae, age=40) 이 출력되는 것을 확인할 수 있다.


      copy 이용하기

      • data class는 copy() 함수가 이미 구현되어 있다.

      • 이를 이용하여 원래 data class로 부터 새로운 data class를 복사하고, 원하는 값을 변경할 수 있다.

      • 08.02.data_class_sample.kt 파일을 다음과 같이 작성하자.

      data class Person(val name: String, var age: Int)
      
      fun main(args: Array<String>) {
        val person01 = Person("UncleBae", 40)
        println(person01)
      
        val person02 = person01.copy(name = "Ruby")
        println(person02)
      }
      • 결과는 다음과 같다.

      Person(name=UncleBae, age=40)
      Person(name=Ruby, age=40)
      • 즉, copy 메소드를 이용하여 원래 값에서 이름만 바꾼 새로운 값을 생성하였다.


      hashCode() 과 equals() 이용하기

      • hashCode() 는 객체 값을 이용하여 해시 코드를 생성한다. 즉, 값의 유니크성을 확인할 수 있도록 해주는 함수이다.

      • equals() 는 객체 내부의 값이 동일한지 검사한다.

      • 다음과 같이 08.03.data_class_sample.kt 파일을 다음과 같이 작성한다.

      data class Person(val name: String, var age: Int)
      
      fun main(args: Array<String>) {
        val person01 = Person("UncleBae", 40)
        val person02 = person01.copy()
        val person03 = person01.copy(name = "Ruby")
      
      
        println("person01: " + person01.hashCode())
        println("person02: " + person02.hashCode())
        println("person03: " + person03.hashCode())
      
        println("-----------------------------------------")
      
        if (person01.equals(person02) == true) {
          println("U1 is equals to U2")
        } else {
          println("U1 is not equals to u2")
        }
      
        if (person01.equals(person03) == true) {
          println("U1 is equals to u3")
        } else {
          print("U1 is not equals to u3")
      
        }
      }
      • 결과는 다음과 같다.

      person01: 276639557
      person02: 276639557
      person03: 79312238
      -----------------------------------------
      U1 is equals to U2
      U1 is not equals to u3
      • 즉, person01에서 copy를 통해서객체를 그대로 복사했다. 이때 hashCode는 둘다 동일한 값을 가진다.

      • 다만, 복사를 하고 해당 값을 변경하면 다른 값이 불러지게 된다.


      반환값 구조화 하기 (Destructing)

      • 데이터 객체로 부터 값을 조회할때 해당 데이터 클래스 값을 분해하여 반환 받을 수 있다.

      • 이를 Destruction이라고 부른다.

      • 08.04.data_class_sample.kt 파일을 다음과 같이 작성하자.

      data class Person(val name: String, var age: Int, val gender: String)
      
      fun main(args: Array<String>) {
        val person01 = Person("UncleBae", 40, "Male")
        val (name, age, gender) = person01 
        println("Name: " + name)
        println("Age: " + age)
        println("Gender: " + gender)
      }
      • 결과는 다음과 같다.

      Name: UncleBae
      Age: 40
      Gender: Male


      componentN 형식으로 값 분해하가.

      • kotlin data class는 자동으로 componentN으로 생성자의 순서대로 값을 가져올 수 있다.

      • 08.05.data_class_sample.kt 파일을 다음과 같이 작성하자.

      data class Person(val name: String, var age: Int, val gender: String)
      
      fun main(args: Array<String>) {
        val person01 = Person("UncleBae", 40, "Male")
        println("Component1: " + person01.component1())
        println("Component2: " + person01.component2())
        println("Component3: " + person01.component3())
      }
      • 결과는 다음과 같다.

      Component1: UncleBae
      Component2: 40
      Component3: Male


      WrapUp

      • data class는 순수하게 데이터를 담기 위한 클래스를 정의할때 유용하다.

      • 내부적으로 toString, equals, hashCode, copy, componentN 등의 함수를 미리 작성되어 있기 때문에 반복적인 보일러플레이트 코드를 상당히 줄일 수 있다.

      • 샘플 코드는: https://www.programiz.com/kotlin-programming/data-class 을 참조했다.


      Sealed class

      • sealed 클래스는 값이 제한된 세트 (제한된 계층구조)의 유형중 하나만 가질 수 있을때 사용된다.


      Sealed class 사용하지 않은경우 문제점

      class Expr
      class Const(val value: Int) : Expr
      class Sum(val left: Expr, val right: Expr) : Expr
      
      fun eval(e: Expr): Int =
        when (e) {
            is Const -> e.value
            is Sum -> eval(e.right) + eval(e.left)
            else ->
                throw IllegalArgumentException("Unknown expression")
        }
      • Expr 클래스는 베이스 클래스이다.

      • Const와 Sum 은 Expr을 상속받은 객체인 것을 알 수 있다.

      • eval 함수에서 Expr 를 파라미터로 받고, 각 자식 클래스의 타입에 따라 특정 일을 수행할때 when 구문을 이용하고 is 를 통해서 특정 클래스 타입일때 각 작업을 수행할 수 있게 된다.

      • 이외의 값이 들어온다면 else 조건에 따라 IllegalArgumentException 을 반환하게 된다. 이 때 else는 필수이며, 없으면 오류가 난다. w

      • when 조건식이 기타 케이스를 검출하지 못하기 때문이다.

      • 위 코드에서 만약 Expr을 상속받는 새로운 자식 클래스를 작성한다면, 위 코드는 else에 걸리고, 원하지 않는 오류를 발생 시킬 수 있다.

      • 이때에는 새로운 서브 클래스가 추가될때 컴파일러가 오류를 반환한다면, 누락되는 구현 없이 새로운 서브 클래스에 대한 대응 작업을 하게 된다.

      • 이 때 사용하는 것이 sealed class 이다.

      • sealed 를 지정하면 위 코드에서 else를 제거하고 좀더 제한적으로 클래스를 사용하도록 할 수 있다.


      Sealed 를 이용하여 바꾼 코드

      sealed class Expr
      class Const(val value: Int) : Expr()
      class Sum(val left: Expr, val right: Expr) : Expr()
      object NotANumber : Expr()
      
      
      fun eval(e: Expr): Int =
        when (e) {
            is Const -> e.value
            is Sum -> eval(e.right) + eval(e.left)
            NotANumber -> java.lang.Double.NaN
        }
      • 이제 위 코드는 else가 없다.

      • 왜냐하면 sealed 를 지정하여 Expr이 상속받는 클래스는 명확히 Const, Sum, NotANumber 로 규정했기 때문에 더이상의 서브 클래스가 없다고 선언했기 때문이다.


      Sealed 를 사용하기 위해 필수 조건

      • 반드시 sealed 를 지정한 동일한 파일에 서브 클래스를 작성해야한다.

      • sealed 클래스는 자체적으로 abstract 속성을 가진다. 그러므로 sealed 클래스는 직접 생성할 수 없다.

      • 기본적으로 sealed class는 private 생성자를 가진다. sealed 클래스는 non-private 생성자를 가질 수 없다.


      Enum과 Sealed의 차이점

      • Enum class와 Sealed class는 유사하게 보인다.

      • enum 의 각 값들은 sealed class처럼 제한되어 사용된다.

      • 차이점은 enum은 단지 단일 인스턴스만을 가지는 반면에, sealed class는 서브 클래스로 상속받으며 여러 인스턴스를 가질 수 있게 된다.


      WrapUp

      • sealed class는 추상 클래스로 동작하며, 하나의 파일에 지정된 서브 클래스들을 하나로 묶어주는 역할을 한다.

      • 그리고 이들을 이용하면 제한된 서브 클래스만을 사용하기 때문에 좀더 엄격한 클래스 관리를 할 수 있게 된다.

      • 동일한 파일에 작성해야하므로, 특정 서브 클래스가 생성이 되면, 처리되어야하는 업무 역시 동일한 파일내에서 작성되도록 하면 생각하지 못한 오류를 방지할 수 있다.

      • from: https://www.programiz.com/kotlin-programming/sealed-class 에서 참조했다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      KIDO 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기