일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 서비스 쓰레드 차이
- 안드로이드 유닛 테스트 예시
- 플러터 설치 2022
- rxjava cold observable
- 클래스
- ANR이란
- android retrofit login
- 서비스 vs 쓰레드
- 안드로이드 레트로핏 사용법
- 안드로이드 라이선스
- 안드로이드 유닛테스트란
- 스택 큐 차이
- 안드로이드 유닛 테스트
- jvm이란
- 큐 자바 코드
- Rxjava Observable
- android ar 개발
- 2022 플러터 설치
- 2022 플러터 안드로이드 스튜디오
- jvm 작동 원리
- 객체
- 안드로이드 라이선스 종류
- 멤버변수
- 안드로이드 레트로핏 crud
- rxjava hot observable
- 자바 다형성
- 스택 자바 코드
- 안드로이드 os 구조
- ar vr 차이
- rxjava disposable
- Today
- Total
나만을 위한 블로그
[Kotlin] 코틀린에서 제공하는 특수 클래스(Data Class, Sealed Class) 본문
코틀린에는 자바와 달리 특수한 클래스가 존재한다. Data Class와 Sealed Class라는 것인데 각각 어떤 것인지 정리한다.
Data Class
코틀린 공식 홈페이지에서 설명하는 Data Class는 아래와 같다.
https://kotlinlang.org/docs/data-classes.html
주요 목적이 데이터를 보유하는 클래스를 만드는 건 드문 일이 아니다. 이런 클래스에서 일부 표준 기능과 유틸리티 기능은 종종 데이터에서 기계적으로 파생된다. 코틀린에선 이를 데이터 클래스라고 하며 데이터로 표시된다
data class User(val name: String, val age: Int)
컴파일러는 기본 생성자에 선언된 모든 속성에서 다음 멤버를 자동으로 파생한다
- equals() / hashCode() 쌍
- User(name=John, age=42) 형태의 toString()
- componentN()은 선언 순서대로 속성에 해당한다
- copy()
생성된 코드의 일관성과 의미 있는 동작을 보장하기 위해 데이터 클래스는 다음 요구사항을 충족해야 한다
1. 기본 생성자에는 하나 이상의 매개변수가 있어야 한다
2. 모든 기본 생성자 매개변수는 val 또는 var로 표시해야 한다
3. 데이터 클래스는 추상, 개방, 봉인 또는 내부가 될 수 없다
또한 데이터 클래스 멤버의 생성은 멤버의 상속과 관련해서 다음 규칙을 따른다
1. 데이터 클래스 본문에 equals(), hashCode() 또는 toString()의 명시적 구현이 있거나 슈퍼클래스의 최종 구현이 있는 경우 이런 함수는 생성되지 않고 기존 구현이 사용된다
2. 상위 유형에 열려 있고 호환 가능한 유형을 반환하는 componentN()이 있는 경우 데이터 클래스에 대해 해당 함수가 생성되고 상위 유형의 함수를 재정의한다. 호환되지 않는 서명이나 최종 서명으로 인해 상위 유형의 기능을 재정의할 수 없는 경우 오류가 보고된다
3. componentN() 및 copy()에 대한 명시적 구현을 제공하는 것은 허용되지 않는다
데이터 클래스는 다른 클래스를 확장할 수 있다(Sealed class 참조)
이런저런 잡다한 말들이 있긴 한데 핵심은 데이터를 보유하는 클래스가 데이터 클래스란 뜻이다. 매우 직관적인 이름이다.
자바에서는 흔히 DTO라고 불리는 게 Data Class와 같다고 볼 수 있다. 단, VO(Value Object)와는 다르다. VO는 읽을 수만 있는 read only 특징을 갖기 때문에 Data Class와는 전혀 다르다.
Data class의 예시는 아래와 같다. 가장 만만한 게 사람이니 Person이라는 Data class를 만든다고 가정한다.
data class Person(val name: String, val address: String, val age: Int)
이름, 주소, 나이라는 변수를 갖는 Person data class를 만든다면 위와 같이 간단하게 끝난다.
이 Person 클래스를 자바로 바꾼다면 아래처럼 된다.
public class Person {
private String name;
private String address;
private int age;
public Person(String name, String address, int age) {
this.name = name;
this.address = address;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
둘을 비교하면 가장 큰 차이점인 getter/setter가 없다. 커스텀 게터세터를 만들지 않는 이상, 코틀린은 게터세터 없이 직접 프로퍼티에 접근해서 사용하기 때문이다.
이 점 때문에 코틀린으로 안드로이드 앱을 만드는 예제를 찾아보면 리사이클러뷰에서 사용하는 경우가 많이 보인다.
그리고 데이터 클래스는 프로퍼티만 선언하면 컴파일러가 equals(), hashCode(), toString()을 자동으로 만들어준다. 자바의 경우 IDE가 생성해주는 걸 사용하거나 개발자 입맛에 맞게 커스텀해서 만들어 사용하는 경우가 대부분이다.
Sealed class
다음은 sealed class다. 코틀린 공식 홈페이지에서 말하는 sealed class는 아래와 같다.
https://kotlinlang.org/docs/sealed-classes.html
sealed class와 인터페이스는 상속에 대한 더 많은 제어를 제공하는 제한된 클래스 계층을 나타낸다. sealed class의 모든 직접 하위 클래스는 컴파일 시간에 알려진다. sealed class가 있는 모듈이 컴파일된 후에는 다른 하위 클래스가 나타날 수 없다. 예를 들어 타사 클라이언트는 코드에서 sealed class를 확장할 수 없다. 따라서 sealed class의 각 인스턴스에는 이 클래스가 컴파일될 때 알려진 제한된 집합의 유형이 있다. sealed interface와 그 구현에 대해서도 동일하게 작동한다. sealed interface가 있는 모듈이 컴파일되면 새 구현이 나타날 수 없다. 어떤 의미에서 sealed class는 열거형 클래스와 유사하다. 열거형 유형에 대한 값 집합도 제한되지만 각 열거형 상수는 단일 인스턴스로만 존재하는 반면 sealed class의 하위 클래스에는 각각 고유한 속성이 있는 여러 인스턴스가 있을 수 있다...(중략)...sealed class 또는 sealed interface를 선언하려면 이름 앞에 selaed 수식자를 넣는다
sealed interface Error
sealed class IOError(): Error
class FileReadError(val file: File): IOError()
class DatabaseError(val source: DataSource): IOError()
object RuntimeError : Error
sealed class는 그 자체로 추상적이며 직접 인스턴스화할 수 없으며 추상 멤버를 가질 수 있다. sealed class의 생성자는 protected(기본값) 또는 private 2가지 가시성 중 하나를 가질 수 있다. sealed class 및 interface의 직접 하위 클래스는 동일 패키지에서 선언해야 한다. 그것들은 최상위 수준이거나 여러 다른 명명된 클래스, 명명된 인터페이스 또는 명명된 개체 내부에 중첩될 수 있다. 하위 클래스는 코틀린의 일반 상속 규칙과 호환되는 한 모든 가시성을 가질 수 있다. sealed class의 하위 클래스에는 적절한 정규화된 이름이 있어야 한다...(중략)
아래는 다른 블로그에서 설명하는 sealed class에 대한 내용이다.
https://medium.com/@kamilbekar/how-to-use-sealed-class-in-kotlin-f186c30a21e2
sealed class는 값이 제한된 집합의 유형 중 하나를 가질 수 있지만 다른 유형은 가질 수 없는 경우 sealed class 계층을 나타내는 데 사용된다. 어떤 의미에선 열거형 클래스의 확장이다. 열거형 유형의 값 집합도 제한되지만 각 열거형 상수는 단일 인스턴스로만 존재하는 반면 sealed class의 하위 클래스는 다음을 포함할 수 있는 여러 인스턴스를 가질 수 있다...(중략)...Enum 클래스와 sealing class는 상당히 유사하다. 열거 유형에 대한 값 집합도 닫힌 클래스로 제한된다. 유일한 차이점은 열거형은 단일 샘플만 가질 수 있지만 하위 클래스의 여러 인스턴스를 가질 수 있는 클래스를 다룬다
sealed class는 미래에 바뀔 수 있지만 현재는 최종적인 것으로 간주되는 계층을 나타내는 데 사용된다.
그리고 위에서 말하듯 enum 클래스를 확장한 개념이라고 볼 수 있는 클래스로 종류별로 하나의 인스턴스만 생성돼 있는 enum 클래스와 달리 sealed class는 인스턴스를 여러 개 생성할 수 있다.
'개인 공부 > Kotlin' 카테고리의 다른 글
[Kotlin] 범위 지정 함수(let, with, run, apply, also)란? (0) | 2022.05.01 |
---|---|
[Kotlin] 코루틴(Coroutine)이란? (0) | 2022.04.27 |
[Kotlin] null 처리 방법 정리 (0) | 2022.02.20 |
[Kotlin] 범위(range)란? in 연산자 사용법 (0) | 2022.02.13 |
[Kotlin] 반복문(for) 사용법 정리 (0) | 2022.02.13 |