Người nhận và người định cư trong Kotlin


86

Ví dụ: trong Java, tôi có thể tự viết getters (do IDE tạo ra) hoặc sử dụng Annotations như @Getter trong lombok - điều này khá đơn giản.

Tuy nhiên, Kotlin có getters và setters theo mặc định . Nhưng tôi không thể hiểu cách sử dụng chúng.

Tôi muốn làm cho nó, giả sử - tương tự như Java:

private val isEmpty: String
        get() = this.toString() //making this thing public rises an error: Getter visibility must be the same as property visibility.

Vậy getters hoạt động như thế nào?

Câu trả lời:


142

Getters và setters được tạo tự động trong Kotlin. Nếu bạn viết:

val isEmpty: Boolean

Nó bằng với mã Java sau:

private final Boolean isEmpty;

public Boolean isEmpty() {
    return isEmpty;
}

Trong trường hợp của bạn, công cụ sửa đổi quyền truy cập riêng tư là dư thừa - isEmpty là riêng tư theo mặc định và chỉ có thể được truy cập bởi getter. Khi bạn cố gắng lấy thuộc tính isEmpty của đối tượng, bạn gọi phương thức get trong thực tế. Để hiểu thêm về getters / setters trong Kotlin: hai mẫu mã dưới đây bằng nhau:

var someProperty: String = "defaultValue"

var someProperty: String = "defaultValue"
    get() = field
    set(value) { field = value }

Ngoài ra, tôi muốn chỉ ra rằng thistrong getter không phải là tài sản của bạn - đó là thể hiện của lớp. Nếu bạn muốn có quyền truy cập vào giá trị của trường trong getter hoặc setter, bạn có thể sử dụng từ dành riêng fieldcho nó:

val isEmpty: Boolean
  get() = field

Nếu bạn chỉ muốn có một phương thức get trong quyền truy cập công khai - bạn có thể viết mã này:

var isEmpty: Boolean
    private set 

do công cụ sửa đổi riêng tư gần bộ truy cập đã đặt, bạn chỉ có thể đặt giá trị này trong các phương thức bên trong đối tượng của mình.


16
In your case the private access modifier is redundantLàm sao? Kotlin doc's nói rằng công cụ sửa đổi mặc định là công khai. kotlinlang.org/docs/reference/visibility-modifiers.html

@ Không có nó có vẻ giống như trường công cộng, nhưng bạn gọi là phương thức getter
Cortwave

Các val isEmpty: Booleansẽ không biên dịch như isEmpty chưa được khởi tạo, phải không? Mới bắt đầu học Kotlin. Ngoài ra, những gì đang xảy ra với get() = field?
Shubham A.

1
@Chiara val's không có setter
chroder

@chroder vâng bạn nói đúng, chắc mình đọc nhầm ... comment bị xóa. Cảm ơn vì đã chỉ ra
Chiara

30

Các quy tắc về công cụ sửa đổi mức độ hiển thị của người truy cập thuộc tính như sau:

  • Khả năng hiển thị của thuộc tính varvà thuộc valtính phải hoàn toàn giống với khả năng hiển thị của thuộc tính, do đó bạn chỉ có thể sao chép rõ ràng công cụ sửa đổi thuộc tính, nhưng nó là thừa:

    protected val x: Int
        protected get() = 0 // No need in `protected` here.
    
  • Khả năng hiển thị của người thiết lập của thuộc vartính phải giống hoặc ít hơn khả năng hiển thị của thuộc tính:

    protected var x: Int
        get() = 0
        private set(x: Int) { } // Only `private` and `protected` are allowed.
    

Trong Kotlin, các thuộc tính luôn được truy cập thông qua getter và setter, do đó không cần phải tạo một thuộc tính privatevới các trình truy cập publicnhư trong Java - trường hỗ trợ của nó (nếu có) đã là riêng tư. Vì vậy, các công cụ sửa đổi khả năng hiển thị trên trình truy cập thuộc tính chỉ được sử dụng để làm cho khả năng hiển thị của setter ít dễ dàng hơn:

  • Đối với thuộc tính có trường sao lưu và trình truy cập mặc định:

    var x = 0 // `public` by default
        private set
    
  • Đối với thuộc tính không có trường sao lưu:

    var x: Int // `public` by default
        get() = 0
        protected set(value: Int) { }
    

Có thể đặt và nhận các loại khác nhau? Đặt x bằng một số "Some String"và trả về cho biết độ dài 11, của chuỗi?
Carel

@Carel, không, hiện tại, trường hợp sử dụng này không được hỗ trợ: các trình truy cập của một thuộc tính phải hoạt động với chính xác loại thuộc tính. Sử dụng một loại khác nhau được bao phủ bằng cách sử dụng một tài sản ủng hộ riêng biệt
hotkey

Em yêu, Kotlin rất gần với Python đến nỗi bạn nghĩ rằng nó sẽ hoạt động khi bạn được nhắc rằng nó đã được gõ ... và tự cắt cổ mình.
Carel

Cảm ơn bạn đã bổ sung quyền truy cập. Tôi đã xóa privatekhỏi một biến và nó có thể truy cập được từ một lớp khác với getter.
CoolMind

Tôi nhận được thông báo "Bộ cài đặt riêng không được phép đối với các thuộc tính mở" khi sử dụng tổ hợp "var x // private set". Được giải quyết bằng cách khai báo là "final var x"
Tom

14

1) Ví dụ mặc định settergettercho tài sản firstName trong Kotlin

class Person {
    var firstName: String = ""
            get() = field       // field here ~ `this.firstName` in Java or normally `_firstName` is C#
            set(value) {
                field = value
            }

}

Sử dụng

val p = Person()
p.firstName = "A"  // access setter
println(p.firstName) // access getter (output:A)

NẾU bạn setterhoặc getterchính xác giống nhau ở trên, bạn có thể loại bỏ nó vì nó là không cần thiết

2) Ví dụ về setter và getter tùy chỉnh.

const val PREFIX = "[ABC]"

class Person {

    // set: if value set to first name have length < 1 => throw error else add prefix "ABC" to the name
    // get: if name is not empty -> trim for remove whitespace and add '.' else return default name
    var lastName: String = ""
        get() {
            if (!field.isEmpty()) {
                return field.trim() + "."
            }
            return field
        }
        set(value) {
            if (value.length > 1) {
                field = PREFIX + value
            } else {
                throw IllegalArgumentException("Last name too short")
            }
        }
}

Sử dụng

val p = Person()
p.lastName = "DE         " // input with many white space
println(p.lastName)  // output:[ABC]DE.
p.lastName = "D" // IllegalArgumentException since name length < 1

Thêm nữa,
tôi bắt đầu học Kotlin từ Java nên tôi thấy khó hiểu fieldpropertyvì trong Java không có property.
Sau một số tìm kiếm, tôi thấy fieldpropertytrong Kotlin trông giống như C # ( Sự khác biệt giữa trường và thuộc tính là gì? )

Dưới đây là một số bài có liên quan mà nói về fieldpropertytrong Java và Kotlin.
java có một cái gì đó tương tự như các thuộc tính C #?
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531

Đúng nếu tôi đã sai lầm. Hy vọng nó sẽ giúp


Cảm ơn bạn, nó thực sự giúp tôi!
marcode_ely

8

Getter trong kotlin theo mặc định là public, nhưng bạn có thể đặt setter thành private và đặt giá trị bằng cách sử dụng một phương thức bên trong một lớp. Như thế này.

/**
* Created by leo on 17/06/17.*/

package foo
class Person() {
var name: String = "defaultValue"
               private set

fun foo(bar: String) {
    name = bar // name can be set here
       }
}

fun main(args: Array<String>) {
  var p = Person()
  println("Name of the person is ${p.name}")
  p.foo("Jhon Doe")
  println("Name of the person is ${p.name}")
}

5

Bạn có thể xem hướng dẫn này để biết thêm thông tin:

Tuy nhiên, một hướng dẫn Kotlin khác dành cho nhà phát triển Android

Tính chất

Trong thế giới Kotlin, các lớp không thể có trường, chỉ có thuộc tính. Từ khóa var cho chúng ta biết thuộc tính có thể thay đổi, ngược lại với val. Hãy xem một ví dụ:

class Contact(var number: String) {

   var firstName: String? = null
   var lastName: String? = null
   private val hasPrefix : Boolean
       get() = number.startsWith("+")

}

Không có nhiều mã, nhưng rất nhiều thứ đang diễn ra ở hậu trường. Chúng tôi sẽ đi qua nó từng bước. Trước hết, chúng tôi tạo Liên hệ lớp cuối cùng công khai.

Đây là quy tắc chính mà chúng ta phải đối mặt: nếu không được chỉ định khác, các lớp là công khai và cuối cùng theo mặc định (nhân tiện, đối với các phương thức của lớp cũng vậy). Nếu bạn muốn kế thừa từ lớp, hãy đánh dấu nó bằng từ khóa mở.


0

Dưới đây là một ví dụ thực tế, thực tế của một bộ thu và thiết lập Kotlin (Xem thêm chi tiết tại đây ):

// Custom Getter
val friendlyDescription get(): String {
    val isNeighborhood = district != null
    var description = if (isNeighborhood) "Neighborhood" else "City"
    description += " in"
    if (isNeighborhood) {
        description += " $city,"
    }
    province?.let {
        if (it.isNotEmpty()) {
            description += " $it,"
        }
    }
    description += " $country"
    return description
}

print(myLocation.friendlyDescription) // "Neighborhood in Denver, Colorado, United States"


// Custom Setter
enum class SearchResultType {
    HISTORY, SAVED, BASIC
}

private lateinit var resultTypeString: String

var resultType: SearchResultType
    get() {
        return enumValueOf(resultTypeString)
    }
    set(value) {
        resultTypeString = value.toString()
    }

result.resultType = SearchResultType.HISTORY
print(result.resultTypeString) // "HISTORY"

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.