728x90
프로퍼티의 접근 - Setter, Getter

프로퍼티의 접근 - Setter, Getter

  • 자바의 필드 : 접근 메소드를 필요로 함
  • 코틀린의 프로퍼티 : 변수 선언 외에 접근 메소드가 별도로 있음
    • Getter/Setter : 코틀린의 프로퍼티 접근 메소드
class Person(var name: String, var age: Int) // 클래스 선언 fun main() { val user = User("Kim", 20) val name = user.name //getter에 의한 프로퍼티 반환 user.age = 25 //setter에 의한 프로퍼티 값 변경 }
  • 게터와 세터의 설정 원리 : 변수 설정 시 get(), set()이 각각 자동으로 선언됨
    • 아래 양식처럼 암묵적으로 선언되며 같은 양식대로 직접 커스텀할 수 있음
Class bar(...) { val A : Int //불변형은 getter만 선언됨 get() = field /* 프로퍼티를 get에 대입 시 무한 재귀 호출이 되기 때문에, 프로퍼티를 가리키는 변수인 field로 별도로 선언됨 */ var B : Int //가변형은 get, set 모두 선언됨 get() = field set(value) { field = value } }

지연 초기화

  • 클래스의 프로퍼티는 null일 수 없으므로 객체 생성 시 초기화가 필요한데, 객체 정보가 나중에 나타나는 경우 나중에 초기화할 방법이 필요
  • lateinit, lazy 키워드로 지연된 초기화 가능
  • lateinit
    • 클래스 간의 의존성이 있는 경우 (특정 클래스가 생성되어야 초기화할 수 있는 경우)
    • 테스트를 위해 임시로 객체를 생성해야 하는 경우
    • var형 프로퍼티만 가능
    • 초기화 전에는 프로퍼티의 getter, setter 사용이 불가
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" //isInitialized = true kildong.test() //"initialized" } ///////////////////////////////////////////////////////// // lateinit을 이용한 클래스 생성의 지연 초기화 data class Person(var name : String, var age : Int) lateinit var person1 : Person //클래스 지연 초기화 fun main() { person1 = Person("Kildong", 30) //생성자 호출 시점에 초기화 }
  • lazy : 호출 시 by lazy로 지연 초기화
    • val에서만 사용 가능, 초기화 후값 변경 불가
    • lazy 키워드의 모드
      • by lazy(mode = SYNCHRONIZED) : 단일 스레드의 사용 보장
      • by lazy(mode = PUBLICATION) : 여러 곳에서 호출될 수 있으나 처음 초기화된 값 사용
      • by lazy(mode = NONE) : 락이 되지 않으므로 여러 스레드의 접근이 가능하나 값이 일관되지 않을 수 있음
class Lazytest { init {println("init block")} val subject by lazy { println("lazy init") "kotlin programming"//subject 접근 시 대입됨 } fun flow() { println("not init") println("subject : $subject") // 이 시점에서 subject가 초기화됨 } } fun main() { val test = Lazytest() test.flow() }
  • by를 이용한 위임
    • 람다식을 사용
    • 한 클래스가 다른 클래스에 위임
    • 위임된 클래스 멤버는 참조 없이 호출
    • <var|val|class> 이름 : 자료형 by 위임자
  • 위임을 쓰는 이유
    • 코틀린 라이브러리는 open되지 않은 클래스(상속 불가)
    • 표준 라이브러리의 복잡한 상속을 방지하나, 기능 확장이 어려움
    • 위임 사용 시 : 클래스 기능에 추가 기능을 구현 가능
interface Animal() { fun eat() {...} } class Cat = Animal() val cat = Cat() class Robot = Animal by cat //RobotCat의 멤버를 사용 가능
  • 위임의 특수 키워드
    • observable : 프로퍼티를 보다가 변경 발생 시 호출
    • vetoable : 반환값에 따른 변경 허용 및 취소
import kotlin.properties.Delegates class User { var name : String by Delegates.observable("NONAME")//observable 매개변수로 name 초기값 설정 { prop, old, new -> //프로퍼티, 기존값, 새로운 값을 매개로 받음 println("$old->$new") //이벤트 발생(name값의 변화) 시 실행 } }

정적 변수와 메서드

  • 코틀린의 클래스는 동적으로 생성
  • 동적 초기화 없이 사용 가능한 변수 = 정적 변수 : 코틀린에서는 컴패니언 객체라고 칭함
  • 사용하지 않아도 메모리에 상주하므로 자주 사용하는 객체에 대해 사용
class Person { var id : Int = 0 var name : String = "kim" companion object // 컴패니언 객체 : 객체 생성 없이 접근 가능 { var lang : String = "Kor" fun work() { println("working") } } } fun main() { println(Person.lang) //인스턴스 생성 없이 출력 가능 Person.lang = "Eng" //변경 가능 Person.work() //메소드 실행 가능 println(Person.name) //name은 companion이 아니므로 에러 }
728x90

+ Recent posts