2017-04-05 22 views
36

Là một nhà phát triển Java, khái niệm về một lĩnh vực sao lưu là một chút nước ngoài với tôi. Given:Lĩnh vực dự phòng Kotlin là gì?

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

Trường sao lưu này phù hợp với điều gì? Kotlin docs cho biết: Các lớp học trong Kotlin không thể có các trường. Tuy nhiên, đôi khi nó là cần thiết để có một lĩnh vực sao lưu khi sử dụng accessors tùy chỉnh. Tại sao? Whats sự khác biệt với việc sử dụng tên thuộc tính chính nó bên trong setter, ví dụ như.

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

Chắc chắn là nhà phát triển Java khái niệm này là thứ mà bạn sử dụng hàng triệu lần mỗi ngày :) Tất cả những trường 'Private SomeClass; ' – Strelok

+4

Sử dụng chính thuộc tính trong setter sẽ dẫn đến việc đệ quy vô tận kể từ khi gán một giá trị cho thuộc tính sẽ luôn gọi setter. – funglejunk

+0

@Strelok tệ của tôi .... Tôi đã giả định rằng 'this.counter = value' này giống với Java tương đương khi đọc tài liệu của Kotlin. –

Trả lời

36

Bởi vì, nói rằng nếu bạn không có field từ khóa, bạn sẽ không thể thực sự thiết lập/lấy giá trị trong get() hoặc set(value). Nó cho phép bạn truy cập vào trường sao lưu trong accessors tùy chỉnh.

Đây là mã Java tương đương với mẫu của bạn:

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

Rõ ràng đây không phải là tốt, như setter chỉ là một đệ quy infinte vào bản thân, không bao giờ thay đổi bất cứ điều gì. Hãy nhớ trong kotlin bất cứ khi nào bạn viết foo.bar = value nó sẽ được dịch sang một cuộc gọi setter thay vì một số PUTFIELD.


EDIT: Kotlin có tính khi java có lĩnh vực, mà là một khái niệm mức khá cao so với các lĩnh vực.

Có hai loại thuộc tính: một loại có trường hậu thuẫn, một trường không có.

Thuộc tính có trường hậu thuẫn sẽ lưu giá trị dưới dạng một trường. Trường đó làm cho lưu trữ giá trị trong bộ nhớ có thể. Ví dụ về thuộc tính đó là các thuộc tính firstsecond của Pair. Thuộc tính đó sẽ thay đổi biểu diễn trong bộ nhớ của Pair.

Thuộc tính không có trường sao lưu sẽ phải lưu trữ giá trị của chúng theo những cách khác hơn là lưu trữ trực tiếp nó trong bộ nhớ. Nó phải được tính từ các thuộc tính khác hoặc chính đối tượng đó. Ví dụ về thuộc tính đó là thuộc tính mở rộng indices của List, không được hỗ trợ bởi một trường, mà là kết quả tính toán dựa trên thuộc tính size. Vì vậy, nó sẽ không thay đổi biểu diễn trong bộ nhớ của List (mà nó không thể làm gì cả vì Java được gõ tĩnh).

+0

Cảm ơn bạn đã trả lời! Của tôi xấu ... Tôi đã giả định rằng 'this.counter = value' là giống nhau với java tương đương. –

7

Trường quay lại rất tốt để chạy xác thực hoặc kích hoạt sự kiện về thay đổi trạng thái. Hãy suy nghĩ về thời gian bạn đã thêm mã vào trình cài đặt/bộ khởi động Java. Các trường sao lưu sẽ hữu ích trong các trường hợp tương tự. Bạn sẽ sử dụng các lĩnh vực sao lưu khi bạn cần kiểm soát hoặc có khả năng hiển thị đối với người định cư/getters.

Khi chỉ định trường có tên trường, bạn thực sự đang gọi trình thiết lập (ví dụ: set(value)). Trong ví dụ bạn có, this.counter = value sẽ recurse vào bộ (giá trị) cho đến khi chúng tôi tràn ngăn xếp của chúng tôi. Sử dụng field bỏ qua mã setter (hoặc getter).

1

Ban đầu, tôi cũng đã có một thời gian khó khăn để hiểu khái niệm này. Vì vậy, hãy để tôi giải thích cho bạn với sự giúp đỡ của một ví dụ.

xem xét lớp Kotlin này

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

Bây giờ khi chúng ta nhìn vào mã này, chúng ta có thể thấy rằng nó có 2 tính chất tức là - size (với accessors mặc định) và isEmpty (với accessors tùy chỉnh). Nhưng nó chỉ có 1 trường, tức là size. Để hiểu rằng nó chỉ có 1 trường, chúng ta hãy xem Java tương đương với lớp này.

Đi tới Công cụ -> Kotlin -> Hiển thị Kotlin ByteCode trong Android Studio. Nhấp vào Decompile.

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; 
    } 
} 

Rõ ràng chúng ta có thể thấy lớp java chỉ có hàm getter và setter cho isEmpty và không có trường nào được khai báo cho nó. Tương tự như vậy trong Kotlin, không có trường sao lưu cho thuộc tính isEmpty, vì thuộc tính không phụ thuộc vào trường đó. Do đó không có trường sao lưu.


Bây giờ, hãy để chúng tôi loại bỏ công cụ tùy chỉnh và thiết lập thuộc tính isEmpty.

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

Và tương đương Java của lớp trên là

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; 
    } 
} 

đây chúng ta thấy cả hai lĩnh vực sizeisEmpty. isEmpty là một lĩnh vực sao lưu vì getter và setter cho tài sản isEmpty phụ thuộc vào nó.

Các vấn đề liên quan