코틀린(Kotlin)

코틀린(kotlin) : 프로퍼티와 필드 Properties and Fields

알통몬_ 2018. 1. 30. 14:47
반응형


공감 및 댓글은 포스팅 하는데

 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 

도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 

만들어 나가겠습니다^^

 


이번 포스팅에서는 코틀린의 프로퍼티와 필드에 대해서 공부합니다.


프로퍼티는 자바에서는 없는 개념입니다.

코틀린 클래스는 프로퍼티를 가질 수 있습니다.

프로퍼티는 var 와 val 로 선언할 수 있습니다.

프로퍼티는 사용은 필드처럼 하지만, 호출하게 되면 함수처럼 호출됩니다.

프로퍼티는 자바의 필드를 사용하듯 사용하면 됩니다. 


class Address {
// 자바의 필드와 다를 바가 없어보이죠?
var name : String = "altongmon"
val birthday : String = "0918"
}

프로퍼티의 전체 문법입니다.

var <프로퍼티이름>[ : 타입] [= <프로퍼티 초기값>]

[<getter>]

[<setter>]

위 값들에서 대괄호 안의 값인 타입, 초기값, getter, setter는 모두 생략 가능합니다.



class Address {

//전체 문법
var gender : String = "male"
get() {
return field + "!!!"
}
set(value) { field = value }
}

fun main(args: Array<String>) {
var address = Address()
println(address.gender)
}

실행해보면 mail!!! 이 출력됩니다.

그리고 val 로 프로퍼티를 선언하게 되면,  set은 선언할 수 없습니다.

//전체 문법
val gender : String = "male"
get() {
return field + "!!!"
}


프로퍼티에 있는 getter 와 setter는 Custom accessor 라고 부르는데요.

위 코드처럼 프로퍼티 선언 내부에 일반 함수처럼 사용 가능합니다.

class Address {

//전체 문법
var gender: String = "male"
get() {
return field + "!!!"
}
set(value) {
field = value + "로 변경"
}

}

fun main(args: Array<String>) {
var address = Address()
// 실제로는 선언한 set(value){...} 안의 코드가 실행됨
address.gender = "female"
//호출하게되면 get() {...} 안의 코드가 실행됨.
println(address.gender)
}

그리고 set() 안의 파라미터 이름은 관습적으로 value를 사용합니다. 자동완성으로 만들어도

value로 들어갑니다. 그냥 value로 쓰시면 됩니다 ㅎㅎ


코틀린의 1.1 버전부터는 getter를 통해서 타입을 추론할 수 있는 경우에,

프로퍼티의 타입을 생략할 수 있습니다.


var size : Int = 0
/*
val isEmpty : Boolean
get() = this.size == 0
*/
val isEmpty
get() = this.size ==
0


프로퍼티의 setter 나 getter 에 접근 제한자나 어노테이션도 사용할 수 있습니다.


var accessor : String = "name"

private set(value) {

}


프로퍼티의 backing field

코틀린 클래스는 field 를 가질 수 없습니다.

field 라는 식별자를 통해 접근할 수 있는 automatic backing field 를 제공합니다.

field 는 프로퍼티의 accessor 에서만 사용가능합니다.

backing field는 항상 생성되는 것이 아니라, accessor 중 하나라도 기본 구현울 사용하거나,

custom accessor 에서 field 식별자를 참조하는 경우에 생성됩니다.

val isEmpty : Boolean
get() = this.size == 0

위 코드는 기본 구현을 사용하지도 않고, custom accessor에서 field 식별자를 사용하지

않기 때문에 backing field가 생성되지 않습니다.


var accessor : String = "name"

private set(value) {
field = value +"backing field"
}


위 같은 경우에 생성됩니다.



프로퍼티의 backing properties

암시적인 backing field 방식이 맞지 않을 경우 backing property를 이용할 수도 있습니다.


private var _name : String? = null
public val name : String
get() {
if(_name == null) {
_name = "unknown"
}
return _name ?: throw AssertionError("null")
}



상수만들기 : const 키워드를 사용합니다.

상수는 클래스 안에 존재할 수 없고, Top-Level이거나 object의 멤버이거나,

String 이나 primitive 타입으로 초기화된 경우에만 사용 가능합니다.

함수 안에 const를 사용하면 에러가 납니다.


Late-Initialized 프로퍼티

일반적으로 프로퍼티는 nonNull 타입으로 선언됩니다.

하지만 종종 nonNull 타입으로 해주고 싶어도, 생성자에서 초기화 해줄 수 없는 경우가

있을 수 있습니다.

ex)

Dependency injection

Butter knife

Unit test 의 setup 함수

이런 경우 lateinit 키워드를 사용해주면, null로 선언이 가능합니다.

* 변수 타입이 val 인 경우, 기본 생성자에서 초기화하는 경우,

 타입에 String? 처럼 notNull 타입인 경우, primitive 타입인 경우,

 클래스 내부에서 사용이 아닌 경우는 사용할 수 없습니다.


이상입니다.

감사합니다.

반응형