내용 보기

작성자

관리자 (IP : 172.17.0.1)

날짜

2020-07-09 06:14

제목

[Kotlin] 코틀린 기초 05 - 프로퍼티


  • 프로퍼티

코틀린 클래스는 생성자, 프로퍼티, 메서드 등으로 구성된다.
var, val로 선언되는 변수들은 실제 프로퍼티로 동작된다.

1
2
3
4
5
6
class User {
 
    val name: String = "test";
    val age: Int = 20;
 
}
cs

위 클래스의 name, age변수는 내부적으로 프로퍼티로 변경되어
결국 다음과 같은 코드로 실행된다.


1
2
3
4
5
6
7
8
9
10
class User {
    var name: String = "test"
        get() = field;
        set(value) {
        field = value;
    }
 
    val age: Int = 20
        get() = field;
}
cs
  • 사용자 정의 프로퍼티
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
class User {
    private var _getting: String = "Hello"
 
    // 사용자 정의 프로퍼티
    var getting: String
        set(value) {
            _getting = "Hello" + value;
        }
    get() = _getting.toUpperCase();
 
    var age: Int = 0
    set(value) {
        if(value > 0) {
            field = value;
        }
        else {
            field = 0;
        }
    }
}
 
 
fun main(args: Array<String>?) {
    val user = User();
    user.getting = "test";
    println(user.getting);
 
    user.age = -1;
    println("age : ${user.age}");
}
cs

실행결과
HELLOTEST
age : 0

  • 프로퍼티 초기화

프로퍼티는 선언과 동시에 초기화 해주어야 한다. 그런데 상황에 따라서 선언과 동시에
초기값을 대입할 수 없을때가 있다. 이때 null로 초기화
하거나 초기화 시점을 미루는 방법이 있다.

// 클래스 init블록에서 초기화

1
2
3
4
5
6
7
8
9
class User {
    var _data1: String;
    var _data2: Int;
 
    init {
        _data1 = "test";
        _data2 = 10
    }
}
cs

// null 허용으로 선언

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class User {
    private var _data1: String = "test"
    private var _data2: String= null;
    private var _data3: Int? = null;
 
    constructor(data1: String, data2: String, data3: Int) {
        _data1 = data1;
        _data2 = data2;
        _data3 = data3;
    }
 
    val data1: String
        get() = _data1;
 
    val data2: String?
        get() = _data2;
}
 
 
fun main(args: Array<String>?) {
    var user: User = User("aaa""bbb"10);
    println(user.data1);
    println(user.data2);
}
cs

실행결과

aaa

bbb


// 늦은 초기화 lateint

1
2
3
4
5
6
7
8
9
10
class User {
    lateinit var lateData: String;
}
 
fun main(args: Array<String>?) {
    var user: User = User();
    user.lateData = "aaa"
    println(user.lateData);
 
}
cs

실행결과

aaa

늦은 초기화 사용 시 주의할 점

  1. lateinit는 var로 선언한 프로퍼티에만 사용할 수 있다.
  2. lateinit는 클래스 몸체에 선언한 프로퍼티에만 사용할 수 있다. 주 생성자 파라메터로는 사용할 수 없다.
  3. lateinit는 사용자 정의 getter/setter를 사용하지 않은 프로퍼티에만 사용할 수 있다.
  4. null 허용 프로퍼티에는 사용할 수 없다.
  5. 기초 타입 프로퍼티에는 사용 할 수 없다. [Int, Double 등]

// 초기화 미루기 by lazy

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
31
class User {
    val name: String by lazy {
        println("i am someData lazy..");
        "hello"
    }
 
    val age: Int by lazy {
        println("i am age lazy..");
        10;
    }
 
    init {
        println("i am init..");
    }
 
    constructor() {
        println("i am constructor..");
    }
}
 
 
var user: User = User();
 
println("name use before");
println("name : ${user.name}");
 
println("name use after");
println("age use before");
println("age : ${user.age}");
 
println("age use after");
cs

실행 결과


i am init..

i am constructor..

name use before

i am name lazy..

name : hello

name use after

age use before

i am age lazy..

age : 10

age use after

  1. 호출 시점에 초기화 진행
  2. val로 선언한 프로퍼티에만 사용 가능
  3. 클래스 몸체 이외에 최상위 레벨에서 사용 가능
  4. 기초 타입에도 사용 가능 [Int, Double 등]
  • 프로퍼티 값 변경 감지

프로퍼티 값이 변경되는 순간을 감지할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import kotlin.properties.Delegates
 
class User {
    var name: String by Delegates.observable("nonValue", {props, old, new ->
        println("old : $old / new : $new");
    })
}
 
val user: User = User();
println(user.name);
 
user.name = "test";
user.name = "test222";
 
println(user.name);
cs

By Delegates.observale로 프로퍼티 값을 초기화하고
이후 프로퍼티의 값이 변경될 때 observale메서드가 호출되면서 해당 프로퍼티의 값 정보를 인자로 받을 수 있다.

출처1

출처2