-
6-3. 특별한 클래스 사용하기 : 인라인 클래스(값 클래스)Study(종료)/Kotlin 22.09.13 ~ 12.18 2022. 10. 23. 20:55
6장
6-1. 특별한 클래스 사용하기 : 이넘(enun) 클래스6-3. 특별한 클래스 사용하기 : 인라인 클래스(값 클래스)
6.3. 인라인 클래스(값 클래스)
프로그램에서 통화(돈)이라는 개념을 처리하고 싶을 때, 서로 다른 통화를 구분없이 섞어서 사용한다면
실수할 가능성도 많고, 복잡해진다.
이 경우 여러 통화를 서로 다른 클래스로 정의해 타입 시스템의 도움을 받아 오류를 줄일 수 있는데,
래퍼 클래스와 유틸리티 함수를 사용하면 이러한 방법을 사용할 수 있다.
class Dollar(val amount: Int) // amount = 센트 class Euro(val amount: Int) // amount = 센트 fun Dollar.toEuro() = .. fun Euro.toDollar() = ..
새로운 통화를 만들 때 마다 래퍼 클래스를 생성해야 하므로 래퍼 클래스를 사용하면 런타임 부가 비용이 발생한다.
위 코드처럼 감싸야 하는 대상이 원시 타입이면 부가 비용 문제가 더 커진다.(런타임에서 실행 시간이 늘어난다)
이 문제 해결을 위해 코틀린은 인라인 클래스(inline class)를 도입했다.
원시 타입의 값과 마찬가지로 부가 비용이 없으므로 인라인 클래스를 값 클래스라고 부르기도 한다.
1) 인라인 클래스 정의하기
인라인 클래스를 정의하려면 inline class를 클래스 이름 앞에 붙여야 한다.
inline class Dollar(val amount: Int) inline class Euro(val amount: Int)
인라인 클래스의 주생성자에는 불변 프로퍼티를 하나만 선언해야 한다.
inline class Dollar(val amount: Int, val x:String) // Error : Inline class must have exactly one primary constructor parameter
런타임에 클래스 인스턴스는 별도의 래퍼 객체를 생성하지 않고 이 프로퍼티의 값으로 표현된다.
인라인 클래스도 자체 함수와 프로퍼티를 포함할 수 있다.
inline class Dollar(val amount: Int){ fun add(d: Dollar) = Dollar(amount + d.amount) val isDebt get() = amount < 0 } fun main(){ println(Dollar(15).add(Dollar(20)).amount) // 35 println(Dollar(100).isDebt) // false }
인라인 클래스도 프로그램 내 nullable-type 변수에 원시값을 대입하는 경우 암시적으로 박싱한다.
최적화를 위해 컴파일러는 가능하면 박싱하지 않은 값을 사용하려고 하지만,
박싱하지 않은 값을 사용할 수 없는 경우, 컴파일러는 인라인되지 않는 형태로 클래스를 사용한다.
인라인 클래스 인스턴스는 다른 어떤 타입의 값으로 캐스팅하지 않고도 정확히 상응하는 (프로퍼티) 타입의
값으로 사용될 수 있는 경우 인라인 될 수 있다 라는 규칙을 기억하자.
fun safeAmount(dollar: Dollar?) = dollar?.amount ?: 0 fun main(){ println(Dollar(15).amount) // inline println(Dollar(15)) // Any? type > not inline println(safeAmount(Dollar(15))) // Dollar? type > not inline }
2) 부호 없는 정수
부호 없는 타입을 기반으로 인라인 클래스로 작성된 부호 없는 정수 타입이 있다.부호 없는 정수 타입은 부호 있는 정수 타입의 이름 앞에 U를 붙여 사용할 수 있다.
val unsignedByte: UByte = 1u // UByte : 0 ~ 255, 1byte val uShort: UShort = 100u // UShort : 0 ~ 65535, 2byte val uInt: UInt = UInt.MAX_VALUE // UInt : 4294967295(2^32-1), 4byte val uLong: ULong = ULong.MAX_VALUE // ULong : 18446744073709551615(2^64-1), 8byte println(uInt.toInt()) // println(1u + 2) // Error : Conversion of signed constants to unsigned ones is prohibited
마치며
그래도 이번장은 짧기도 하고 내용역시 부담이 많이 없었다.
사실 원래 스터디날이 기사 시험날이라 기사 공부하고, 그날은 좀 쉬고싶어서 스터디 참가를 못한다고 했는데.
카카오 서버가 터져버려서 아예 그날 스터디 진행을 못했다.
이번장이 부담이 없는 대신 다음장은 부담이 좀 많이 된다.
다음장은 컬렉션과 I/O 자세히 알아보기이고, 무려 60쪽이나 된다..
다 정리할 수 있을지는 모르겠지만, 할수 있는 만큼 최대한 해봐야겠다
반응형'Study(종료) > Kotlin 22.09.13 ~ 12.18' 카테고리의 다른 글
7-1 컬렉션과 I/O 자세히 알아보기 : 컬렉션 타입(2) (0) 2022.10.29 7-1 컬렉션과 I/O 자세히 알아보기 : 컬렉션 타입(1) (0) 2022.10.28 6-2. 특별한 클래스 사용하기 : 데이터 클래스(data class) (0) 2022.10.22 6-1. 특별한 클래스 사용하기 : 이넘(enun) 클래스 (0) 2022.10.13 5-5. 고급 함수와 함수형 프로그래밍 활용하기 : 수신 객체가 있는 호출 가능 참조 (0) 2022.10.10