굥뷰를 햡시댜

[Kotlin] Properties and Fields 본문

언어/Kotlin

[Kotlin] Properties and Fields

GodZ 2019. 4. 25. 00:27

1. Property 선언

  • 코틀린 클래스는 Property를 가질 수 있음( var(mutable) / val(read-only) )
class Address {
    var name: String = "Kotlin"
    val city: String = "Seoul"
}
  • Property 사용은 자바의 필드를 사용하듯이 하면 됨
fun copyAddress(address: Address): Address {
    val result = Address()
    result.name = address.name
    //...
    return result
}

 

2. Property 문법

//전체 문법
var <propertyName>[: <ProopertyType>] [=<property_initializer]
    [<getter>]
    [<setter>]
    
/*
-> 생략 가능한 옵션들
  -> PropertyType - property_initializer로 타입을 추론 가능할 경우 생략 가능!
  -> property_initializer
  -> getter - 코틀린에서는 선언과 동시에 자동으로 getter가 만들어진다(var, val)
  -> setter - 코틀린에서는 선언과 동시에 자동으로 setter가 만들어진다(var, val은 불가능)
              -> val은 선언과 동시에 초기화 해줘야하고 1번만 할당 가능하기 때문에 setter가 지원되지 않음 
*/
  • ex)
fun main(args: Array<String>) {
    var obj = Address()
    println(obj.name)
}

class Address {
    var name: String = "Kotlin"
        get() {
            return field + "!!!"
        }
        set(value) {
            field = value
        }
}

//-> 출력 결과
//Kotlin!!!

 

3. var (mutable) Property

  • ex)
class Address {
    //default getter와 setter
    //타입은 Int
    var initialized = 1
    
    
    
    //error: 오류 발생
    //default getter와 setter를 사용한 경우
    //명시적인 초기화가 필요함
    var allByDefault: Int?
}

 

4. val (read-only) Property

  • var대신 val 키워드 사용
  • setter가 없음
class Address {
    //default getter
    //타입은 Int
    val initialized = 1
    
    //error: 오류 발생
    //default getter
    //명시적인 초기화가 필요
    val allByDefault: Int?
}

 

5. Custom accessors ( getter, setter )

  • custom accessor는 Property 선언 내부에 일반 함수처럼 선언할 수 있음
  • getter
val isEmpty: Boolean
    get() = this.size == 0
  • setter
//관습적으로 setter의 Parameter의 이름은 value임(변경은 가능함)
var stringRepresentation: String
    get() = this.toString()
    set(value) {
        setDataFromString(value)
    }

 

6. Property

  • accessor에 가시성 변경이 필요하거나 어노테이션이 필요한 경우 기본 accessor의 수정 없이 body 없는 accessor를 통해 정의 가능
var setterVisibility: String = "abc"
    private set
var setterWithAnnotation: Any? = null
    @Inject set
  • Body를 작성해도 무방함
var setterVisibility: String = "abc"
    private set(value) {
        field = value
    }

 

7. Backing Fields

  • 코틀린 클래스는 field를 가질 수 없음
  • field라는 식별자를 통해 접근할 수 있는, automatic backing field를 제공함
  • field는 Property의 accessor에서만 사용가능
//the initializer value is written directly
//to the backing field
var counter = 0
    set(value) {
        if(value>=0) field = value
    }

 

8. Backing Fields 생성 조건

  • accessor중 1개라도 기본 구현을 사용하는 경우
  • custom accessor에서 field 식별자를 참조하는 경우
//the initializer value is written directly to the backing field
var counter = 0
    set(value) {
        if(value >= 0) field = value
    }
  • 아래의 경우 backing field를 생성하지 않음
val isEmpty: Boolean
    get() = this.size == 0	//get에서 field를 사용하지 않기 때문

 

9. Backing Properties

  • "implicit backing field" 방식이 맞지 않는 경우에는 "backing property"를 이용할 수도 있음
  • ex) 명시적으로 객체를 생성하는 프로그래밍을 하고 싶을때 사용!!!
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
    get() {
        if(_table == null) {
            _table = HashMap()
        }
        return _table ?: throw AssertionError("null ")
    }

 

10. Compile-Time Constants

  • const modifier를 이용하면 컴파일 타임 상수를 만들 수 있음
  • 조건 -> Top-level 이거나 object의 멤버이거나 String으로 초기화된 경우
const val SUBSYSTEM_DEPRECATED.String = "This subsystem is deprecated"

@Deprecated(SUBSYSTEM_DEPRECATED)
fun foo() {...}

 

11. Late-initialized Properties

  • 나중에 초기화되는 Property
  • 일반적으로 Property는 non-null 타입으로 선언되는데 간혹 non-null타입 property를 사용하고 싶지만, 생성자에서 초기화를 해줄 수 없는 경우가 있음( Dependency injection, Butter knife, Unit test의 setup 메소드)
public class MyTest {
    lateinit var subject: TestSubject	//lateinit을 써서 나중에 초기화할 것이라고 알림
    
    @SetUp fun setup() {
        subject = TestSubject()
    }
    
    @Test fun test() {
        subject.method()	//dereference directly
    }
}
  • 객체가 constructor에서는 할당되지 못하지만 여전히 non-null 타입으로 사용하고 싶은 경우 Lateinit modifier를 사용 가능
  • 조건
  • 클래스의 바디에서 선언된 프로퍼티만 가능
  • 기본생성자에서 선언된 프로퍼티는 안됨
  • var 프로퍼티만 가능
  • custom accessor가 없어야 함
  • non-null 타입이어야 함
  • primitive 타입이면 안됨

'언어 > Kotlin' 카테고리의 다른 글

[Kotlin] Inheritance  (0) 2019.04.24
[Kotlin] Class  (0) 2019.04.24
[Kotlin] Packages, Return and Jumps  (0) 2019.04.24
[Kotlin] Control Flow  (0) 2019.04.24
[Kotlin] Basic Types  (0) 2019.04.23
Comments