Kotlinのゲッターとセッター


89

たとえば、Javaでは、(IDEによって生成された)自分でゲッターを作成したり、ロンボクで@Getterのようなアノテーションを使用したりできます。これは非常に簡単でした。

ただし、Kotlinにはデフォルトでゲッターとセッターがあります。でも使い方がわかりません。

私はそれを作りたいと言いましょう-Javaに似ています:

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

では、ゲッターはどのように機能しますか?

回答:


148

ゲッターとセッターはKotlinで自動生成されます。あなたが書く場合:

val isEmpty: Boolean

これは、次のJavaコードと同じです。

private final Boolean isEmpty;

public Boolean isEmpty() {
    return isEmpty;
}

あなたの場合、プライベートアクセス修飾子は冗長です-isEmptyはデフォルトでプライベートであり、ゲッターによってのみアクセスできます。オブジェクトのisEmptyプロパティを取得しようとすると、実際にはgetメソッドが呼び出されます。Kotlinのゲッター/セッターをより深く理解するために:以下の2つのコードサンプルは同じです:

var someProperty: String = "defaultValue"

そして

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

またthis、ゲッターではあなたの財産ではなく、クラスインスタンスであることを指摘したいと思います。ゲッターまたはセッターでフィールドの値にアクセスしたい場合は、予約語fieldを使用できます。

val isEmpty: Boolean
  get() = field

パブリックアクセスでgetメソッドのみが必要な場合は、次のコードを記述できます。

var isEmpty: Boolean
    private set 

setアクセサーの近くにあるprivate修飾子により、この値はオブジェクト内のメソッドでのみ設定できます。


17
In your case the private access modifier is redundantどうやって?Kotlin docによると、デフォルトの修飾子はパブリックです。kotlinlang.org/docs/reference/visibility-modifiers.html

@Nothing yesそれはパブリックフィールドのように見えますが、
内部で

val isEmpty: BooleanisEmptyがまだ初期化されていないとして、右をコンパイルしないのだろうか?Kotlinを学び始めたばかりです。また、何が起こっているのget() = fieldですか?
Shubham A. 2017

1
@Chiaraにvalはセッターがありません
chroder 2018

@chroderはい、あなたは正しいです、私は間違って読んだに違いありません...コメントが削除されました。ご指摘いただきありがとうございます
Chiara

30

プロパティアクセサの可視性修飾子に関する規則は次のとおりです。

  • ゲッターの可視性varvalプロパティは、プロパティの可視性とまったく同じである必要があります。したがって、プロパティ修飾子を明示的に複製することしかできませんが、冗長です。

    protected val x: Int
        protected get() = 0 // No need in `protected` here.
    
  • varプロパティのより適切な可視性は、プロパティの可視性と同じか、それよりも許容度低い必要が あります。

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

Kotlinでは、プロパティは常にgetterとsetterを介してアクセスされるため、Javaのようにアクセサーを使用してプロパティprivateを作成する必要はありません。そのバッキングフィールド(存在する場合)はすでにプライベートです。したがって、プロパティアクセサの可視性修飾子は、セッターの可視性の許容度を下げるためにのみ使用されます。public

  • バッキングフィールドとデフォルトアクセサを備えたプロパティの場合:

    var x = 0 // `public` by default
        private set
    
  • バッキングフィールドのないプロパティの場合:

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

1つのセットで異なるタイプを取得できますか?x someに等しく設定し、文字列の"Some String"長さ、、を返し11ますか?
カレル

@Carel、いいえ、現時点では、このユースケースはサポートされていません。プロパティのアクセサーは、プロパティのタイプとまったく同じように動作する必要があります。別のタイプの使用は、別のバッキングプロパティ
ホットキー

ダーン、KotlinはPythonに非常に近いので、入力されたことを思い出したときに機能すると思います...そして自分の喉を切ります。
カレル

アクセス修飾子をありがとう。private変数から削除すると、getterを使用して別のクラスからアクセスできるようになりました。
CoolMind

「varx // private set」の組み合わせを使用すると、「プライベートセッターはオープンプロパティに許可されていません」というメッセージが表示されます。「
Tom

15

1)実施例のデフォルトsettergetterのために財産 firstNameKotlinで

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

}

使用する

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

IFあなたsetterかがgetterあるとまったく同じ上記のことがあるので、あなたはそれを削除することができます、不要な

2)カスタムセッターとゲッターの例。

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")
            }
        }
}

使用する

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

もっと
私は私が混乱していますので、JavaからKotlinを学び始めるfieldproperty、Javaでノーがあるためproperty
いくつか検索するfieldproperty、KotlinではC#のように見えます(フィールドとプロパティの違いは何ですか?

ここでの話をいくつかの関連ポストであるfieldpropertyJavaとKotlinに。
JavaにはC#プロパティに似たものがありますか?
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531

私が間違っている場合は私を訂正してください。お役に立てば幸いです


ありがとう、それは本当に私を助けます!
marcode_ely

8

kotlinのGetterはデフォルトでpublicですが、setterをprivateに設定し、クラス内の1つのメソッドを使用して値を設定できます。このような。

/**
* 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

詳細については、このチュートリアルを参照してください。

Android開発者向けのさらに別のKotlinチュートリアル

プロパティ

Kotlinの世界では、クラスにフィールドを含めることはできず、プロパティのみを含めることができます。varキーワードは、valとは対照的に、プロパティが変更可能であることを示します。例を見てみましょう:

class Contact(var number: String) {

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

}

コードはそれほど多くありませんが、舞台裏で多くのことが起こっています。 ステップバイステップで説明します。まず、パブリックファイナルクラスContactを作成しました。

これは私たちが直面しなければならない主要なルールです。特に指定がない限り、クラスはデフォルトでパブリックでファイナルです(ちなみに、クラスメソッドについても同じです)。クラスから継承する場合は、openキーワードでマークします。


0

Kotlinのゲッターとセッターの実際の実例を次に示します(詳細はこちらをご覧ください)。

// 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"

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.