Post

[Kotlin] 6. 프로퍼티와 초기화

※ “Do it! 코틀린 프로그래밍” 을 참고하여 작성하였습니다.

06-1 프로퍼티의 접근

  • 코틀린에서 게터와 세터가 작동하는 방식

    • class 클래스 이름(val a: Int, var b: Int): 클래스 이름 뒤에 프로퍼티를 설정
    • 클래스로 객체를 생성한 다음, .(점)으로 프로퍼티에 접근
      • ex: user.name, user.age
  • 기본 게터와 세터 직접 지정하기

    var은 get, set 모두 가능 / val은 get만 가능

    • var 예시

      1
      2
      3
      4
      5
      
      var name: String= _name
      		get()= field
      		set(value){
      				field= value
      		}
      
    • val 예시

      1
      2
      
      val id: Int= _id
      		get()= field
      
    • field(보조 필드): 프로퍼티를 참조하는 변수

      value: 세터의 매개변수로 외부로부터 값을 가져옴

      → value는 다른 문자열이어도 됨

  • 커스텀 게터와 세터의 사용

    커스텀 게터와 세터: 사용자가 직접 게터와 세터를 정의하면서 새로운 내용을 작성하는 것

    • 보조 프로퍼티의 사용

      • 보조 필드를 사용하지 않는 경우,
      • 임시적으로 사용할 프로퍼티를 선언해놓고 게터나 세터에서 사용할 수 있음
    • 프로퍼티의 오버라이딩

      • 상위 클래스로부터 상속받은 하위 클래스에서 게터와 세터를 재정의할 수 있음

        → 단, 상위 클래스 앞에 open 키워드 필수

06-2 지연 초기화와 위임

  • lateinit을 사용한 지연 초기화

    • lateinit의 제한
      • var로 선언한 프로퍼티만 가능
      • 프로퍼티에 대한 게터와 세터를 사용할 수 없음
    • 프로퍼티 초기화 여부 확인
      • ::프로퍼티.isInitialized

    [객체 지연 초기화하기]

    • 함수 밖에 lateinit 키워드로 생성자의 값 할당 없이 객체를 먼저 생성하고,
    • main() 에서 생성자와 함께 객체를 초기화
  • lazy를 사용한 지연 초기화

    • lazy의 특징
      • 호출 시점에 by lazy {…} 의 정의에 의해 블록 부분의 초기화를 진행
      • 불변 변수인 val(읽기 전용)에서만 사용 가능
      • val이므로 값을 다시 변경할 수 없음

    [객체 지연 초기화하기]

    • by lazy: person 객체의 지연 초기화

      1
      2
      3
      4
      5
      6
      7
      8
      
      class Person(val name: String, val age: Int)
          
      fun main(){
      		val person: Person by lazy{
      				Person("Kim", 23)
      		}
      		println("person.name= ${person.name}") // 이 때 초기화, person.name= Kim
      }
      
    • lazy: 변수에 lazy 객체가 위임되므로, 객체에 접근(초기화)할 때 .value를 한 번 더 써주어야 함

      1
      2
      3
      4
      5
      6
      
      class Person(val name: String, val age: Int)
          
      fun main(){
      		val personDelegate= lazy { Person("Hong", 40) }
      		println("personDelegate.value.name= ${personDelegate.value.name}")
      }
      
  • lazy 모드(아리까리 하다.. 초기화의 접근 범위에 따라 달라지는건지?)

    • SYNCHRONIZED: lock을 사용해 단일 스레드 만이 사용하는 것을 보장(default)
    • PUBLICATION: 여러 군데에서 호출될 수 있으나 처음 초기화된 후 반환값을 사용
    • NONE: lock을 사용하지 않기 때문에 빠르지만, 다중 스레드가 접근할 수 있음
  • by를 이용한 위임

    • 클래스 위임

      [형식] class 클래스 이름: 자료형 by 위임자

      • 위임된 클래스의 메소드는 정적 메소드로 생성됨
      • 즉, 위임된 클래스의 메소드나 프로퍼티를 활용할 수 있음
    • 프로퍼티 위임

      [형식] (var or val) 프로퍼티: 자료형 by 위임자

    • observable() 함수의 위임

      • 프로퍼티 값이 변경되는지 감시

        1
        2
        3
        4
        5
        6
        7
        8
        
        import kotlin.properties.Delegates
              
        class User{
        		var name: String by Delegates.observable("NONAME"){
        				prop, old, new ->
        				println("$old -> $new"
        		}
        }
        
    • vetoable() 함수의 위임

      • Boolean 값이 나오도록 조건을 설정해서, 조건이 맞지 않으면 값 할당을 거부

        1
        2
        3
        4
        5
        6
        7
        8
        9
        
        import kotlin.properties.Delegates
              
        fun main(){
        		var max: Int by Delegates.vetoable(0){
        				prop, old, new ->
        				new > old // 조건에 맞지 않으면 거부권 행사
        		}
        		...
        }
        

06-3 정적 변수와 컴패니언 객체

: 프로그램을 실행할 때 고정적으로 가지는 메모리로 객체 생성 없이 사용할 수 있음

  • 컴패니언 객체

    • Explanation

      • 실제 객체의 싱글톤으로 정의
      • 객체가 서로 동일한 정보를 가질 때 하나의 메모리만 유지해 자원의 낭비를 줄일 수 있음
    • 예시

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      class Person{
      		var id: Int= 0
      		companion object{
      				var language: String= "Korean"
      				fun work(){
      						println("working. . .")
      				}
      		}
      }
          
      fun main(){
      		println(Person.language) // Korean
      		Person.work() // working. . .
      }
      
    • 코틀린에서 자바의 static 멤버 사용하기

      • 클래스명.프로퍼티
      • 클래스명.함수()
    • 자바에서 코틀린 컴패니언 객체 사용하기

      [코틀린]

      • const val 프로퍼티= “hi~”
      • @JvmStatic fun 함수()= println(”hi~”)
      • @JvmField val 프로퍼티= 클래스()

      [자바]

      • 애노테이션 사용: 클래스.함수()
      • 애노테이션 사용X: 클래스.Companion.함수()
  • 최상위 함수

    or 패키지 레벨 함수: 클래스없는 함수

    • 자바에서 최상위 함수 접근하기

      • 클래스Kt.최상위 함수()

      • @file:JvmName(”PKLevel”)

        PKLevel.최상위 함수()

    • object 클래스: 선언과 동시에 객체 생성

      • 예시: object OCustomer{ … }
      • 생성자 선언 X
      • 자바에서 object로의 접근: 클래스.INSTANCE.함수()
    • object 표현식: 하위 클래스를 만들지 않고 오버라이딩

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      open class Superman(){
      		open fun fly()= println("Flying in the air.")
      }
          
      fun main(){
      		val pretendedMan= object: Superman(){
      				override fun fly= println("I'm not a superman. I can't fly!")
      		}
      }
      
    • 활용 예시

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      interfact Shape{
      		fun onDraw()
      }
          
      val triangle= object: Shape{ // 상위 인터페이스를 한번 객체로 써서 오버라이딩
      		override fun onDraw(){
      				...
      		}
      }
      
      1
      2
      3
      4
      5
      6
      7
      
      fun foo(){ // 객체(adHoc)는 필요하지만 상위 인터페이스나 클래스가 없는 경우
      		val adHoc= object{
      				var x: Int= 0
      				var y: Int= 0
      		}
      		println(adHoc.x + adHoc.y)
      }
      
This post is licensed under CC BY 4.0 by the author.