초기화를 바로 하지 않고 지연시켰다가 하는 것
선언은 앞부분에서 해도 사용을 중간부터 하면 미리 초기화 할 필요가 없다.(낭비)
객체의 정보가 나중에 필요한 경우 나중에 초기화 할 방법이 필요하다.
lateinit과 lazy 키워드를 사용한다.
val로 선언된 불변변수에는 lateinit을 사용할 수 없다.
원래는 name을 바로 초기화해야 하지만 lateinit 키워드로 선언해서 name프로퍼티를 따로 초기화 할 때 초기화된다.
객체도 lateinit으로 선언만 해 놓고 나중에 생성자를 호출 할 때 지연 초기화 할 수 있다.
::name은 프로퍼티를 참조형으로 불러오기 위해 사용하는 것이다.
::을 이용해서 불러와야 프로퍼티를 객체처럼 참조형을 불러와 객체 대상으로 메소드를 사용하는 것처럼 initialized로 초기화 검사를 할 수 있다.
초기화 하지 않고 접근하면 예외가 발생한다.
lazy를 통해 초기화 한 값은 변경할 수 없다.
subject 라는 프로퍼티를 by lazy의 블록을 이용해서 초기화한다.
subject에 접근하기 전까지는 초기화되지 않다가 최초 접근하면 그 때 초기화된다.
또한 lazy 블록은 람다식의 형태로 마지막 식이 반환되어서 subject에 할당된다
객체를 lazy를 이용해서 지연초기화 할 수 있다.
person은 by lazy를 이용해서 지연초기화했다.
블록의 마지막 식에 생성자를 넣어서 person에 객체가 할당되도록 한다.
personDelegate는 위임 변수를 사용한 초기화로 by 없이 lazy만 사용해서 작성한 것이다. 두개 같은 방법인데 표현만 다르다고 생각하면 된다.
person과 personDelegate 모두 처음으로 접근할 때 초기화된다.
personDelegate는 위임변수이므로 personDelegate.value.name으로 프로퍼티에 접근한다.
즉 personDelegate는 객체가 아니라 변수 자체로 취급해서 value로 객체를 가져와서 name에 접근한다.
SYNCHRONIZED는 한번에 하나만 초기화해서 안전하지만 NONE에 비해 성능이 떨어질 수 있다.
표준 라이브러리를 변경하지 않고 위임을 통해 기능을 사용하면서 추가할 수도 있다.
CarModel 클래스의 주생성자에서 Car 객체를 매개변수로 받아서 by impl로 위임받는다. 따라서 Car 인터페이스의 메소드를 참조 없이 자기 메소드 인 것처럼 사용 가능하다.
by로 위임을 하지 않는다면 impl.go() 와 같이 사용해야 한다.
kotlin.properties.Delegates를 import 해야한다.
User 클래스의 name 프로퍼티를 ovservable을 이용해서 위임한다.
name의 값이 변경되는지 감시할 수 있다.
observable의 인자로 초기값과 람다식을 전달한다. 람다식을 따로 {}로 빼서 전달한 상황이다.
람다식 내에서는 prop, old, new 세 변수를 가지고 처리할 수 있다.
veotable은 observable과 비슷하지만 조건이 있다는 점이 다르다.
예시에서는 new>old 일 때만 max값을 새로 할당하고 아닐 경우 할당하지 않는다.