Kotlin 지원 필드는 무엇입니까?


93

Java 개발자로서 지원 필드의 개념은 나에게 약간 이질적입니다. 주어진:

class Sample {
    var counter = 0 // the initializer value is written directly to the backing field
    set(value) {
        if (value >= 0) field = value
    }
}

이 지원 필드는 무엇에 유용합니까? Kotlin 문서 는 다음과 같이 말했습니다.

Kotlin의 클래스는 필드를 가질 수 없습니다. 그러나 때로는 사용자 지정 접근자를 사용할 때 지원 필드가 필요합니다 .

왜? setter 내에서 속성 이름 자체를 사용하는 것과 다른 점은 무엇입니까?

class Sample {        
    var counter = 0
    set(value) {
        if (value >= 0) this.counter = value // or just counter = value?
    }
}

18
setter에서 속성 자체를 사용하면 속성에 일부 값을 할당하면 항상 setter가 호출되므로 끝없는 재귀가 발생합니다.
funglejunk

1
@Strelok my bad .... this.counter = valueKotlin의 문서를 읽을 때 Java와 동일 하다고 가정했습니다 .
Yudhistira Arya

5
문서 는 필드 대 속성에 대한 것입니다.
avinash

답변:


87

예를 들어 field키워드가 없으면 get()또는 에서 값을 실제로 설정 / 가져올 수 없습니다 set(value). 사용자 지정 접근 자의 지원 필드에 액세스 할 수 있습니다.

다음은 샘플과 동등한 Java 코드입니다.

class Sample {
    private int counter = 0;
    public void setCounter(int value) {
        if (value >= 0) setCounter(value);
    }
    public int getCounter() {
        return counter;
    }
}

setter는 그 자체로 무한한 재귀이며 아무것도 변경하지 않기 때문에 분명히 이것은 좋지 않습니다. kotlin에서 쓸 때마다 . foo.bar = value대신 setter 호출로 변환됩니다 PUTFIELD.


편집 : Java에는 필드가 있지만 Kotlin에는 필드보다 높은 수준의 개념 인 속성 이 있습니다.

속성에는 두 가지 유형이 있습니다. 하나는 지원 필드가있는 것이고 다른 하나는없는 것입니다.

지원 필드가있는 속성은 값을 필드 형식으로 저장합니다. 이 필드는 메모리에 값을 저장할 수있게합니다. 이러한 속성의 예는의 firstsecond속성입니다 Pair. 이 속성은의 메모리 내 표현을 변경합니다 Pair.

지원 필드가없는 속성은 메모리에 직접 저장하는 것보다 다른 방법으로 값을 저장해야합니다. 다른 속성 또는 객체 자체에서 계산해야합니다. 이러한 속성의 예는의 indices확장 속성으로 List, 필드에서 지원되지 않지만 size속성을 기반으로 계산 된 결과입니다 . 따라서 List(Java가 정적으로 형식화되어 있기 때문에 전혀 할 수없는) 의 메모리 내 표현을 변경 하지 않습니다.


답변 해주셔서 감사합니다! 내 나쁜 ... 나는 그것이 this.counter = value자바와 동일 하다고 가정하고 있었다 .
Yudhistira Arya

문서화 된 곳이 있나요? 감사합니다 :)
Alston


1
모호한 설명이 많이 있습니다. a field가 기존 멤버 변수에 대한 참조 또는 포인터와 비슷 하다고 분명히 말할 수없는 이유는 무엇입니까? (가) 이후 get/set즉시 followes counter따라서, field키워드에 대한 참조이다 counter. 권리?
eigenfield

@typelogic이 답변은 C / C ++가 아닌 Java / JS 배경 (이전에는 Kotlin / Native가 없음)을 가진 프로그래머에게 가장 적합합니다. 애매 모호한 것은 다른 사람들을위한 빵과 버터입니다.
glee8e

32

처음에 저도이 개념을 이해하는 데 어려움을 겪었습니다. 예를 들어 설명하겠습니다.

이 Kotlin 클래스 고려

class DummyClass {
    var size = 0;
    var isEmpty
        get() = size == 0
        set(value) {
            size = size * 2
        }
}

이제 코드를 살펴보면 size(기본 접근 자 포함) 및 isEmpty(사용자 지정 접근 자 포함) 두 가지 속성이 있음을 알 수 있습니다 . 그러나 그것은 단지 하나의 필드를 가지고 size있습니다. 필드가 하나뿐임을 이해하기 위해이 클래스에 해당하는 Java를 살펴 보겠습니다.

Tools-> Kotlin-> Show Kotlin ByteCode in Android Studio로 이동합니다. 디 컴파일을 클릭하십시오.

   public final class DummyClass {
   private int size;

   public final int getSize() {
      return this.size;
   }

   public final void setSize(int var1) {
      this.size = var1;
   }

   public final boolean isEmpty() {
      return this.size == 0;
   }

   public final void setEmpty(boolean value) {
      this.size *= 2;
   }
}

분명히 우리는 자바 클래스에에 대한 getter 및 setter 함수 만 있고 이에 대해 isEmpty선언 된 필드가 없음을 알 수 있습니다. 마찬가지로 Kotlin에는 property isEmpty에 대한 지원 필드가 없습니다 . 속성이 해당 필드에 전혀 의존하지 않기 때문입니다. 따라서 지원 필드가 없습니다.


이제 isEmpty속성 의 사용자 지정 getter 및 setter를 제거하겠습니다 .

class DummyClass {
    var size = 0;
    var isEmpty = false
}

그리고 위의 클래스에 해당하는 Java는 다음과 같습니다.

public final class DummyClass {
   private int size;
   private boolean isEmpty;

   public final int getSize() {
      return this.size;
   }

   public final void setSize(int var1) {
      this.size = var1;
   }

   public final boolean isEmpty() {
      return this.isEmpty;
   }

   public final void setEmpty(boolean var1) {
      this.isEmpty = var1;
   }
}

여기에서 필드 sizeisEmpty. 속성에 isEmpty대한 getter 및 setter가 isEmpty종속 필드이므로 지원 필드 입니다.


4
좋은 설명입니다. 주셔서 감사합니다
소누 산지 브에게

1
설명 해주셔서 감사합니다. 저도 Java에서 Kotlin으로 왔고 속성 개념은 저에게 생소합니다. 하지만 당신과 가이드 덕분에 이해했습니다. :)
Yamashiro Rion

하나님 께서 당신을 축복하실 수 있습니다.
Andrea Cioccarelli

솔직히 사실을 인용하는 대답이 마음에 듭니다. C #field키워드가 필요하지 않기 때문에 여전히 의심 스럽습니다. Kotlin의 언어 개선으로이 이상한 field키워드 를 제거 하고 무기력 한 영혼이 무한 재귀의 심연에 빠지는 것을 방지 할 수 있습니까?
eigenfield

9

지원 필드는 유효성 검사를 실행하거나 상태 변경시 이벤트를 트리거하는 데 유용합니다. Java setter / getter에 코드를 추가 한 시간을 생각해보십시오. 지원 필드는 유사한 시나리오에서 유용합니다. setter / getter를 제어하거나 가시성을 확보해야 할 때 지원 필드를 사용합니다.

필드 이름 자체로 필드를 할당 할 때 실제로 setter (예 :)를 호출합니다 set(value). 당신이 가지고있는 예제에서, this.counter = value스택이 오버플로 될 때까지 set (value)로 재귀 할 것입니다. 사용 field하면 setter (또는 getter) 코드를 우회합니다.


죄송합니다. 설명에 설명해야 할 용어가 포함되어 있습니다. 그런 다음 먼저 Java 시나리오를 인용 한 다음 갑자기 경고없이 실제 Kotlin 문으로 전환합니다. 키워드에 대한 Kotlin의 필요성 fieldC # 이 아니므로 여기에서 인용 한 것보다 더 나은 설명이 필요합니다.
eigenfield

2

나의 이해는 사용하는 필드 의 속성 값에 대한 참조로 식별자를 GET 또는 설정 변경하거나에서 속성의 값을 사용하려는 경우, GET 또는 세트 .

예를 들면 :

class A{
    var a:Int=1
        get(){return field * 2}    // Similiar to Java: public int geta(){return this.a * 2}
        set(value) {field = value + 1}
}

그때:

var t = A()
println(t.a)    // OUTPUT: 2, equal to Java code: println(t.a * 2)
t.a = 2         // The real action is similar to Java code: t.a = t.a +1
println(t.a)    // OUTPUT: 6, equal to Java code: println(t.a * 2)

0

용어 backing field는 수수께끼로 가득 차 있습니다. 사용 된 키워드는 field입니다. get/set방법은, 바로 옆에 관한 멤버 변수 다음 될 얻을 또는 설정 이 도어 보호 메커니즘을 통해 방법. field키워드는 될 멤버 변수를 참조 설정 하거나 얻을 . 현재 Kotlin에서는 get 또는 set 보호 문 메서드 내부에서 직접 멤버 변수를 참조 할 수 없습니다. 안타깝게도 get 또는 set을 다시 호출 하여 런타임을 심연으로 이끌 기 때문에 무한 재귀가 발생하기 때문입니다 .

하지만 C # 에서는 getter / setter 메서드 내에서 멤버 변수를 직접 참조 할 수 있습니다. 나는이 field키워드가 현재 Kotlin이 그것을 구현하는 방법 이라는 아이디어를 제시하기 위해이 비교를 인용 하고 있지만, 이후 버전에서 제거되고 무한 재귀를 초래하지 않고 직접 멤버 변수를 직접 참조 할 수 있기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.