+ 항공대학교 김철기 교수님의 객체 지향 프로그래밍 과목 내용를 정리한 글입니다.
최상위 프로퍼티
- 클래스에 소속되지 않은 프로퍼티는 전역 변수/상수의 역할을 한다.
- public/internal/private 등의 가시성 지정이 가능하다.
private val prefix = "Hello, " // 전역 변수
// private 선언이기 때문에 다른 파일에서는 호출이 불가능하다.
fun main() {
val name = readLine()?: return // null이면 return
println("$prefix $name")
}
늦은 초기화 (lateinit)
- 생성자에서 초기화되지는 않지만, 프로그램 흐름 상 실사용 시 초기화되는 것이 명백한 변수에는 lateinit이라는 예약어로 표기하여 null값이 불가함을 표기할 수 있다. (var의 늦은 초기화)
- 실제 초기화가 안될 경우 UninitializedPropertyAccessException이 발생하므로 !!를 사용한 것과 비슷한 특성을 가진다. (위험성을 갖는다.)
=> 가능하면 by lazy를 권장한다. (val의 늦은 초기화)
import java.io.File
class Content {
lateinit var text: String
// 실 사용되기 전 loadFile이 반드시 사전 호출되어 초기화 됨을 프로그래머가 확인해야한다.
fun loadFile(file: File) {
text = file.readText()
}
}
fun main() {
val c = Content()
println(c.text) // kotlin.UninitializedPropertyAccessException 발생
}
커스텀 접근자
- 프로퍼티에 대한 접근을 함수로 수행한다.
class Person (val firstName: String, val familyName: String) {
val fullName: String
get() { // fullName이 호출될 때마다 get함수 호출
println("get() has been called.")
return "$firstName $familyName"
}
}
fun main() {
val p = Person("Charlie", "Kim")
println(p.fullName) // get 함수 호출
}
- 식이 본문인 형태의 사용도 가능하다.
val fullName: String
get() = "$firstName $familyName"
뒷받침하는 필드
- 커스텀 접근자 게터를 사용하는 경우도 메모리에 뒷받침하는 필드를 두어 값을 저장할 수 있다.
- 이 경우 field라는 예약어로 해당 필드에 접근한다.
class Person (val firstName: String, val familyName: String, age: Int) {
val age = age // 뒷받침하는 필드
get() {
println("Getter was called.")
return field
}
}
fun main() {
val p = Person("Charlie", "Kim", 40)
println(p.age) // get 함수 호출
}
가변 프로퍼티를 위한 세터
- var 프로퍼티를 위해서는 set(value)를 통하여 setter를 둘 수 있다.
class Person (val firstName: String, val familyName: String) {
var age: Int? = null
set(value) {
if (value != null && value <= 0) { // 널이 아니고 음수라면
throw IllegalArgumentException("Invalid age: $value") // 예외 발생
}
field = value // age = value
}
}
fun main() {
val p = Person("Charlie", "Kim")
p.age = 20 // 커스텀 setter 호출
println(p.age)
}
뒷받침하는 필드가 없는 가변 프로퍼티
- getter와 setter을 모두 생성해야한다.
class Person (var firstName: String, var familyName: String) {
var fullName // 뒷받침하는 필드가 없는 프로퍼티
get() = "$firstName $familyName"
set(value) {
val names = value.split(" ")
if (names.size != 2) throw IllegalArgumentException("Invalid full name: $value")
firstName = names[0]
familyName = names[1]
}
}
fun main() {
val p = Person("Charlie", "Kim")
p.fullName = "Gildong Hong"
println(p.firstName)
println(p.familyName)
println(p.fullName)
}
프로퍼티 접근자를 통한 접근 통제
- 프로퍼티의 get / set 각각에 대하여 다른 접근자를 두어 접근을 통제할 수 있다.
=> 보통 클래스 외부에서는 값을 변경할 수 없지만, 읽을 수는 있도록 할 때 사용한다.
import java.util.*
class Person (name: String) {
var lastChanged: Date? = Date() // 가장 최근에 변경된 날짜 저장
private set // 클래스 외부에서는 값을 변경할 수 없다.
var name: String = name
set(value) {
lastChanged = Date() // 현재 날짜로 변경
field = value
}
}
fun main() {
val p = Person("Gildong")
p.name = "Charlie"
println(p.lastChanged)
}
지연 계산 프로퍼티 (by lazy)
- 프로퍼티 접근 때까지 프로퍼티의 값에 대한 연산을 지연한다. (val만 가능하다.)
- lateinit과는 다르게 널 안전하므로 권장된다.
import java.io.File
class Content(var file: File) {
val text by lazy {
println("reading text from file")
file.readText()
}
}
fun main() {
val c = Content(File("Quiz.txt"))
println("Before access text")
println(c.text) // text를 읽을 때만 파일을 읽는다.
}'Study > Kotlin Study' 카테고리의 다른 글
| [Kotlin] 함수형 프로그래밍 (0) | 2023.09.22 |
|---|---|
| [Kotlin] 객체 (Object) (0) | 2023.09.17 |
| [Kotlin] 널 가능성 (0) | 2023.09.12 |
| [Kotlin] 함수 (4) | 2023.09.03 |
| [Kotlin] 클래스 정의하기 (1) | 2023.08.28 |