티스토리 뷰

자바에는 없는 개념인 지연생성자에 대해서 알아보도록 합시다.


우리가 자바로 개발을 할때는 초기화하는 코드를 만들어줄때 생성자에서 만들어주어야 하는 불편함이 있습니다. 궂이 불편하다고 이야기를 한다면요


그런데 이런 부분을 사용할때 초기화를 하여서 불편함을 줄여버릴수 있는 방법이 있습니다.


그걸 kotlin에서는 해줍니다. 물론 swift도 해주지만요.


class Test {
 
    private val name = "test"
}
cs


이렇게 말이죠... 이렇게 만들게 되면 아름답게 한줄로 만들수는 있지만 만약 저 data에 조건으로 접근을 할 것이라면 사용 자체를 하지 않을것이기 때문에 낭비입니다.


class Test {
 
    private var name: String = null
 
    private func getName() {
        if (name == null) {
            name = "test"
        }
 
        return data
    }    
}
cs


이런식으로 아주 자바스럽게 작성을 할수도 있겠죠 ㅎㅎ


그렇지만 우리는 조금 더 개선된 방법으로 만들어 보도록 하죠.

왜냐면 저렇게 만들면 객체를 만드는 부분과 선언한 부분이 너무 갈라져 보여서 좋지 않습니다.


private var string: String= null
    get() {
        if (string == null) {
            string = "test"
        }
            
        return string
    }
cs


이런 코드를 만들수 있을것입니다.


대략 이건 선언한 부분과 생성하는 부분이 붙어 있어서 보기에는 조금 더 좋은것 같습니다.

이 코드를 조금 더 개선해볼까 합니다. kotlin에서는 지연생성자를 조금 더 지원하거든요


lateinit 이용


class TestActivity : BaseActivity() {
 
    private lateinit var name: String
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
 
        name = "AAA"
    }
}
cs


음... 정말 아무것도 아닙니다. 우리가 위에는 옵셔널로 선언하였던 변수들을 나중에 생성하겠다는 의미입니다.

그래서 약간 조심하여야 하는것이 이것은 변수에 접근시에 초기화가 되어 있다고 판단을 하고 그냥 접근하게 됩니다.


lateinit의 조건


- var. 즉 mutable 만 사용이 가능합니다.
- null로 초기화가 불가능합니다. 당연한것이 옵셔널이 아니기 때문에 초기화가 불가능합니다.
- 초기화를 하고 난 이후에 변수에 접근하여야 합니다. 안 그러면 Exception 발생
- 변수에 setter, getter의 정의가 불가능합니다.
- primitive type에서는 사용이 불가능하다 Int, Double등
cs


lateinit 초기화 확인


kitlin 1.2부터 가능하다고 합니다만...

이거 null check하면 그냥 되는거 아닌가 싶은 정도 입니다.


class TestActivity : BaseActivity() {
 
    private lateinit var name: String
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
 
        name = "AAA"
 
        if (::name.isInitialized) {
            
        }
    }
}
cs


lateinit을 디컴파일 한다면?


이런 형태가 된다고 하는데 흡사 위에 제가 자바로 작성해둔것과 비슷하기는 합니다.

단지 접근할수 없을 경우에 Exception을 던지는것이 조금 다르기는 하네요.


@NotNull
public String name;
 
@NotNull
public final String getName() {
    String name500 = this.name;
    if(this.name == null) {
        Intrinsics.throwUninitializedPropertyAccessException("name");
    }
 
    return name500;
}
 
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
 
    this.name = "AAA";
    String name500 = this.name;
 
    if (this.name == null) {
        Intrinsics.throwUninitializedPropertyAccessException("name");
    }
}
cs


by lazy


조금 더 엘레강스합니다.


class TestActivity : BaseActivity() {
 
    private val name: String by lazy {
        "AAA"
    }
}
cs


응? 할것 같기도 하네요.

뭐가 이렇게 짧아? 할것 같습니다.


swift에서는 위의 두가지를 이것을 lazy var 하나로만 사용을 하는데요.


그냥 초기화가 필요한 부분이 있다면 저렇게 넣어주기만 하면 됩니다.

대신에... 초기화가 되고 변경을 할수 없으니 그건 잘 맞추어서 개발하는것이 좋을것 같습니다.


객체를 선언해서 아래에서 다시 값을 가지고 생성하여야 하는 부분에서 좋습니다.


by lazy 조건


- by lazy 부분은 한번만 호출되고 자신의 값으로 가지게 됩니다.
- val. 즉 immutable으로만 사용이 가능합니다.
- 값을 변화할수 없습니다.
- 초기화를 위해서는 함수명이라도 한번 적어줘야 합니다.
- lazy동작은 기본적으로 synchronized로 동작합니다. 그래서 안정성이 있습니다.
cs


by lazy 옵션


enum 값으로 Thread의 옵션을 정의할수 있습니다. 성능에 지대한 영향을 미치지 않는다면 저는 Sychronized를 사용할것 같네요...


public enum class LazyThreadSafetyMode {
 
    /**
     * Locks are used to ensure that only a single thread can initialize the [Lazy] instance.
     */
    SYNCHRONIZED,
 
    /**
     * Initializer function can be called several times on concurrent access to uninitialized [Lazy] instance value,
     * but only the first returned value will be used as the value of [Lazy] instance.
     */
    PUBLICATION,
 
    /**
     * No locks are used to synchronize an access to the [Lazy] instance value; if the instance is accessed from multiple threads, its behavior is undefined.
     *
     * This mode should not be used unless the [Lazy] instance is guaranteed never to be initialized from more than one thread.
     */
    NONE,
}
cs


이렇게 쓰시면 됩니다.


private val name: String by lazy(LazyThreadSafetyMode.NONE) {
    "AAA"
}
cs


위에 적은거처럼 swift에서는 두가지의 모습을 한번에 사용하는 lazy var 가 존재합니다.

swift가 kotlin을 배껴서 거의 비슷하거든요. 크크.

나중에 swift부분은 정리해서 올리도록 하겠습니다.


괜히 코드를 많이 치는 개발자가 되지 않길 바랍니다.

물론 코드 라인수로 돈을 계산하는 회사가 아직도 있기는 하지만요.

크크


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함