모든 내용은 Do it! 코틀린 프로그래밍을 바탕으로 정리한 것입니다.
데이터 클래스
특정 동작을 가지지 않고 오로지 데이터 저장을 위해 사용한다면 일반적인 클래스가 가지는 구현부가 필요 없음
→ 자원의 낭비를 막고자 오로지 데이터 저장에 초점을 맞춘 데이터 클래스 제공
데이터 전달을 위한 데이터 클래스
DTO(Data Transfer Object) : 데이터 전달을 위한 객체
POJO(Plain Old Java Object) : 자바에서 부르는 데이터 전달을 위한 객체
- DTO는 구현 로직을 가지고 있지 않고 순수한 데이터 객체를 표현함
- 속성과 속성을 접근하고자 하는 getter/setter를 가짐
- 추가적으로 toString(), equals() 등과 같은 데이터를 표현하거나 비교하는 메서드를 가짐
- DTO를 사용하는 이유? DTO는 데이터를 주고받는 표준 방법이 됨
- 제어 로직을 위한 컨트롤러, 사용자와 상호작용을 위한 뷰, 데이터 표현을 위한 모델 등으로 나뉘는데 데이터를 주고 받는 일은 어디서든 자주 일어나는 일임
- 표준과 같은 약속을 정하면 전송하거나 받고자 하는 어떤 요소든 데이터를 쉽게 다룰 수 있음
BUT, 코틀린에서는 내부적으로 자동 생성함
코틀린의 프로퍼티 = 필드(변수) + getter/setter
데이터 클래스 선언
data class Customer(var name: String, var email: String)
- data 키워드를 사용하여 선언
- 주 생성자는 최소한 하나의 매개변수를 가져야 함
- 주 생성자의 모든 매개변수는 val, var로 지정된 프로퍼티여야 함
- 데이터 클래스는 abstract, open, sealed, inner 키워드를 사용할 수 없음 → 오로지 데이터를 기술하는 용도임
데이터 클래스가 자동 생성하는 메서드
- equals() : 두 객체의 내용이 같은지 비교하는 연산자
- hashCode() : 객체를 구별하기 위한 고유한 정숫값 생성, 데이터 세트나 해시 테이블을 사용하기 위한 하나의 생성된 인덱
- copy() : 빌더 없이 특정 프로퍼티만 변경해서 객체 복사하기
- toString() : 데이터 객체를 읽기 편한 문자열로 반환하기
- componentN() : 객체의 선언부 구조를 분해하기 위해 N번째 프로퍼티에 상응하는 메서드
val cus1 = Custommer("J", "jun@mail.com")
val cus2 = Custommer("J", "jun@mail.com")
println(cus1 == cus2) // 연산자 == 은 내부적으로 equals()을 호출하는 것과 같음
println(cus1.equals(cus2))
// 객체를 구별하기 위한 고유한 정숫값을 생성
// 만일 두 객체가 동등하다면 동일한 정숫값 생성
println("${cus1.hashCode()}, ${cus2.hashCode()}")
val cus3 = cus1.copy(name = "Alice")
println(cus1.toString()) // 객체를 읽기 쉽게 표현
println(cus3.toString())
객체 디스트럭처링
디스트럭처링(Destructuring) : 객체가 가지고 있는 프로퍼티를 개별 변수로 분해하여 할당하는 것
val (name, email) = cus1
println("name = $name, email = $email")
// 특정 프로퍼티가 필요 없는 경우
val (_, email) = cus1
// 개별적으로 프로퍼티를 가져올 수 있음
val name2 = cus1.component1()
val email2 = cus1.component2(
- 변수를 선언할 때 소괄호를 사용하여 분해하고자 하는 객체를 지정함
- 특정 프로퍼티가 필요 없는 경우, 언더스코어(_)를 사용하여 제외
- componentN() 메서드를 사용하여 N번째 프로퍼티를 개별적으로 가져올 수 있음
내부 클래스 기법
클래스 내부에 또 다른 클래스를 설계하여 두는 이유는
- 독립적인 클래스로 정의하기 모호한 경우나
- 다른 클래스에서는 잘 사용하지 않지만 내부에서만 사용하고 외부에서는 접근할 필요가 없을 때가 있기 때문
- 너무 남용하면 클래스의 의존성이 커지고 코드가 읽기 어려워짐
자바 | 코틀린 |
정적 클래스 (Static Class) : static 키워드를 가지고, 외부 클래스를 인스턴스화하지 않고 바로 사용 가능한 내부 클래스 |
중첩 클래스 (Nested Class) : 객체 생성 없이 사용 가능 |
멤버 클래스 (Member Class) : 인스턴스 클래스로도 불리며 외 부 클래스의 필드나 메서드와 연동하는 내부 클래스 |
이너 클래스 (Inner Class) : 필드나 메서드와 연동하는 내부 클래스로 inner 키워드가 필요함 |
지역 클래스 (Local Class) : 초기화 블록이나 메서드 내의 블록에서만 유효한 클래스 |
지역 클래스 (Local Class) : 클래스의 선언이 블록 안에 있는 지역 클래스임 |
익명 클래스 (Anonymous Class) : 이름이 없고 주로 일회용 객체를 인스턴스화하면서 오버라이드 메서드를 구현하는 내부 클래스. 가독성이 떨어지는 단점이 있음 |
익명 객체 (Anonymous Object) : 이름이 없고 주로 일회용 객체를 사용하기 위해 object 키워드를 통해 선언됨 |
중첩 클래스
코틀린의 중첩 클래스는 기본적으로 정적(static) 클래스처럼 다뤄짐
→ 객체 생성 없이 접근 할 수 있음
- 중첩 클래스의 메서드는 객체 생성 없이 호출될 수 있음
- 중첩 클래스는 바로 바깥 클래스의 멤버에 접근할 수 없음
이너 클래스
inner 키워드 사용
단순히 내부에 작성된 중첩 클래스와는 다른역할을 함
- 클래스 안에 이너 클래스를 정의할 수 있는데 이때 이너 클래스는 바깥 클래스의 멤버에 접근할 수 있음
- private 멤버에도 접근이 가능함
지역 클래스
특정 메서드의 블록이나 init 블록과 같이 블록 범위에서만 유효한 클래스
→ 블록 범위를 벗어나면 사용되지 않음
- 외부 프로퍼티 접근이 가능함
익명 객체
자바에서는 익명 이너 클래스라는 것을 제공하여 일회성으로 객체를 생성해 사용
코틀린에서는 object 키워드를 사용하는 익명 객체로 같은 기능을 수행
- 다중 인터페이스를 구현할 수 있음
- 인터페이스로부터 만들어진 객체는 이름이 없으며 일회성으로 사용됨
- 호출될 때마다 일회성의 객체 인스턴스가 만들어지는 것
실드 클래스와 열거형 클래스
실드 클래스
실드(Sealed) : '봉인된' - 안전하게 보관하기 위해 묶어 두는 것
미리 만들어 놓은 자료형들을 묶어 제공하기 때문에 어떤 의미에서는 열거형(Enum) 클래스의 확장으로도 볼 수 있음
- sealed 키워드를 class와 함께 사용
- 그 자체는 추상 클래스와 같기 때문에 객체를 만들 수 없음
- 생성자도 기본적으로는 private이며 private이 아닌 생성자는 허용하지 않음
- 같은 파일 안에서는 상속이 가능하지만, 다르파일에서는 상속이 불가능
- 블록 안에 선언되는 클래스는 상속이 필요한 경우 open 키워드로 선언될 수 있음
// 방법 1 ------------------------------------------------------
sealed class Result {
open class Success(val message: String): Result()
class Error(val code: Int, val message: String): Result()
}
class Status: Result()
class Inside: Result.Success("Status")
// 방법 2 ------------------------------------------------------
sealed class Result
open class Success(val message: String): Result()
class Error(val code: Int, val message: String): Result()
class Status: Result()
class Inside: Result.Success("Status")
열거형 클래스
여러 개의 상수를 선언하고 열거된 값을 조건에 따라 선택할 수 있는 특수한 클래스
- 실드 클래스처럼 다양한 자료형을 다루지 못함
- enum 키워드와 함께 선언할 수 있음
- 자료형이 동일한 상수를 나열할 수 있음
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
enum class DayOfWeek(val num: Int) {
MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5)
SATURDAY(6), SUNDAY(7)
}
val day = DayOfWeek.SATURDAY
when(day.num) {
1, 2, 3, 4, 5 -> println("Weekday")
6, 7 -> println("Weekend!")
}
enum class Color(val r: Int, val g: Int, val b: Int) {
RED(255, 0, 0), ..., ORANGE(255, 165, 0);
fun rgb() = (r*256+g)*256+b
}
fun main(args: Array) {
println(Color.RED.rgb())
- 각 상수의 값은 매개변수를 통해 초기화될 수 있음
- 필요할 경우 메서드를 포함할 수 있는데 세미콜론(;)을 사용해 열거한 상수 객체를 구분함
애노테이션 클래스
애노테이션(Annotation) : 코드에 부가 정보를 추가하는 역할
@ 기호와 함께 나타내는 표기법으로 컴파일러나 프로그램 실행 시간에서 사전 처리를 위해 사용함
- annotation 키워드를 사용해 클래스에 선언
- 애노테이션 클래스를 선언하면 @를 붙여서 사용할 수 있음
- 애노테이션은 속성을 사용하여 정의함
- @Target : 애노테이션이 지정되어 사용할 종류(클래스, 함수, 프로퍼티 등)를 정의
- @Retention : 애노테이션을 컴파일된 클래스 파일에 저장할 것인지 실행 시간에 반영할 것인지 결정
- @Repeatable : 애노테이션을 같은 요소에 여러 번 사용 가능하게 할지를 결정
- @MustBeDocumented : 애노테이션이 API의 일부분으로 문서화하기 위해 사용
- 애노테이션은 클래스 앞, 메서드 앞, 프로퍼티 앞에 사용할 수 있음
- 표준 애노테이션
- @JvmName : filter()라는 이름을 자바에서 각각 filterStrings()와 filterInts()로 바꿔주는 것
- @JvmStatic : 자바의 정적 메서드로 생성할 수 있게 해줌
- @Throw : 코틀린의 throw 구문이 자바에서도 포함되도록 함
- @JvmOverloads : 코틀린에서 기본값을 적용한 인자에 함수를 모두 오버로딩 해줌
애노테이션 클래스 제작은 프레임워크를 만들지 않는 이상 잘 사용하지 않는다고 하니 이쯤에서 그만하겠습니다 ;)
'Kotlin > Kotlin 프로그래밍' 카테고리의 다른 글
[Kotlin] 문자열(String) (0) | 2021.05.21 |
---|---|
[Kotlin] 배열(Array) (0) | 2021.05.18 |
[Kotlin] 제네릭(Generic) (0) | 2021.05.18 |
[Kotlin] 다양한 클래스와 인터페이스 (3) (0) | 2021.05.13 |
[Kotlin] 다양한 클래스와 인터페이스 (1) (0) | 2021.04.21 |
[Kotlin] 프로퍼티와 초기화 (0) | 2021.04.20 |
[Kotlin] 클래스와 객체 (2) (0) | 2021.04.19 |
[Kotlin] 클래스와 객체 (1) (0) | 2021.04.16 |
댓글