fun main(){
val user = User(1, "Sean", 30)
val name = user.name // 게터에 의한 값 획득
user.age = 41 // 세터에 의한 값 지정, 당연히 var(가변형) 일때만 가능
}
class User(_id: Int, _name: String, _age: Int){
// 프로퍼티
val id: Int = _id
get() = field
// field : 프로퍼티를 참조하는 변수로 보조 필드로 불림
// 프로퍼티를 대신할 임시 필드로 만일 프로퍼티를 직접 사용하면 게터나 세터가 무한 호출되는 재귀에 빠짐
var name: String = _name
get() = field
set(value) { // value : 세터의 매개변수로 외부로부터 값을 가져옴
field = value
}
var age: Int = _age
get() = field
set(value) {
field = value
}
}
class User(_id: Int, _name: String, _age: Int){
// 프로퍼티
val id: Int = _id
get() = field
var name: String = _name
get() = field
set(value) {
field = value.toUpperCase()
}
}
class Person {
lateinit var name: String // 늦은 초기화를 위한 선언
fun test(){
if(!::name.isInitialized) { // 로퍼티의 초기화 여부 판단
println("not initialized")
}
else {
println("initialized")
}
}
}
fun main() {
val kildong = Person()
kildong.test() // "not initialized"
kildong.name = "Kildong" // 이 시점에서 초기화됨(지연 초기화)
kildong.test() // "initialized"
}
data class Person(var name: String, var age: Int)
latinit var person1: Person // 객체 생성의 지연 초기화
fun main() {
person1 = Person("Kildong", 30) // 생성자 호출 시점에서 초기화됨
}
class LazyTest {
init {
println("init block") // (2)
}
val subject by lazy {
println("lazy initialized") // (6)
"Kotlin Programming" // (7) lazy 반환값
}
fun flow() {
println("not initialized") // (4)
println("subject one: $subject") // (5) 최초 초기화 시점
println("subject two: $subject") // (8) 이미 초기화된 값 사용
}
}
fun main() {
val test = LazyTest() // (1)
test.flow() // (3)
}
private val model by lazy(mode = LazyThreadSfetyMode.NONE) {
Injector.app().transactionsModel() // 이 코드는 단일 스레드의 사용이 보장될 때
}
< val|var|class > 프로퍼티 혹은 클래스 이름 : 자료형 by 위임자
interface Animal {
fun eat() { ... }
...
}
class Cat : Animal { }
val cat = Cat()
class Robot : Animal by cat // Animal의 정의된 Cat의 모든 멤버를 Robot에 위임함
// cat은 Animal 자료형의 private 멤버로 Robot 클래스 내에 저장
// Cat에서 구현된 모든 Animal의 메소드는 정적 메소드로 생성
// 따라서, Animal에 대한 명시적인 참조를 사용하지 않고도 eat()을 바로 호출
interface Car {
fun go(): String
}
class VanImpl(val power: String): Car{
override fun go() = "는 짐을 적재하며 $power 마력을 가집니다."
}
class SportImpl(val power: String): Car {
override fun go() = "는 경주용에 사용되며 $power 마력을 가집니다."
}
class CarModel(val model: String, impl: Car): Car by impl {
fun carInfo() {
println("$model ${go()}") // 참조 없이 각 인터페이스 구현 클래스의 go를 접근
}
}
fun main() {
val myDamas = CarModel("Damas 2010", VanImpl("100"))
val my350z = CarModel("350Z 2008", SportImpl("350"))
myDamas.carInfo() // "Damas 2010는 짐을 적재하며 100마력을 가집니다."
my350z.carInfo() // "350Z 2008는 경주용에 사용되며 350마력을 가집니다."
}
import kotiln.properties.Delegates
class User {
// observable은 값의 변화를 감시하는 일종의 콜백 루틴
var name: String by Delegates.observable("NONAME") { // (1) 프로퍼티를 위임
prop, old, new -> // (2) 람다식 매개변수로 프로퍼티, 기존값, 새로운 값
println("$old -> $new") // (3) 이부분은 이벤트가 발생할 때만 실행됨
}
}
fun main() {
val user = User()
user.name = "Kildong" // (4) 값이 변경되는 시점에서 첫 이벤트 발생
user.name = "Dooly" // (5) 값이 변경되는 시점에서 두번째 이벤트 발생
}
import kotiln.properties.Delegates
fun main() {
var max: Int by Delegates.vetoable(0) { // (1) 초기값은 0
prop, old, new ->
new > old // (2) 조 건에 맞지 않으면 거부권 행사
}
println(max) // 0
max = 10
println(max) // 10
max = 5
// 여기서는 기존값이 새 값보다 크므로 false 따라서 5를 재할당하지 않는다.
println(max) // 10
}
class Peron {
var id: int = 0
var name: String = "Youngdeok"
companion object {
var language: String = "Korean"
fun work() {
println("working...")
}
}
}
fun main() {
println(Person.language) // 인스턴스를 생성하지 않고 기본값 사용
Person.language = "English" // 기본값 변경 가능
println(Person.language) // 변경된 내용 출력
Person.work() // 메서드 실행
// println(Person.name) // name은 companion object가 아니므로 에러
}
부스트코스 코틀린강좌를 참고하였습니다.