Kotlin 覆盖getValue和setValue以capselate一对

Kotlin 覆盖getValue和setValue以capselate一对,kotlin,Kotlin,假设我有以下课程: class Person() { var age: Pair<String, Int> = Pair("person_age", 23) // override getValue and setValue here } 当然,我可以为每个属性编写自己的getter和setter方法,但Kotlin的一个优点是,您必须编写较少的样板代码,这样会丢失这些代码。以下内容可能已经足够: class Person() { var age : Int =

假设我有以下课程:

class Person() {
    var age: Pair<String, Int> = Pair("person_age", 23)
    // override getValue and setValue here
}

当然,我可以为每个属性编写自己的getter和setter方法,但Kotlin的一个优点是,您必须编写较少的样板代码,这样会丢失这些代码。

以下内容可能已经足够:

class Person() {
  var age : Int = 23 // public by default
  private /* or internal */ fun toAgePair() = "person_age" to age // narrow visibility
}
因此,您的所有代码都访问年龄,如您所示:

val p = Person()
p.age = 25
if (p.age <= 30) ...
访问配对内容的备选方案有:Pair.first、Pair.second或,例如:

或者:

val p = Person()
val (name, age) = p.toAgePair()
// age = 25 // setting will not work however (and it wouldn't set the actual value inside the Pair if it would contain vars)
if (age < 30) // accessing is OK
但是,如果我理解正确的话,你可以访问这两个值,而这两个值在一开始可能是你不想要的。
您可以使用自己的数据类和var来克服设置部分,但同样,您并不能从中获得任何东西。

以下内容可能已经足够:

class Person() {
  var age : Int = 23 // public by default
  private /* or internal */ fun toAgePair() = "person_age" to age // narrow visibility
}
因此,您的所有代码都访问年龄,如您所示:

val p = Person()
p.age = 25
if (p.age <= 30) ...
访问配对内容的备选方案有:Pair.first、Pair.second或,例如:

或者:

val p = Person()
val (name, age) = p.toAgePair()
// age = 25 // setting will not work however (and it wouldn't set the actual value inside the Pair if it would contain vars)
if (age < 30) // accessing is OK
但是,如果我理解正确的话,你可以访问这两个值,而这两个值在一开始可能是你不想要的。 您可以使用自己的带有var的数据类来克服设置部分,但同样,您并不能从中获得什么

现在,我想要capselate实际对,并且只希望用户读取/写入对的第二个值

假设这意味着您希望第一个值是最终值,而不是第二个值,则有一些选项

如果您只希望其中一个值是可写和可读的,请不要使用一对。它不是设计用来这样使用的。一对中的所有项目都是VAL

如果您想要一对,可以这样做:

class Person(var age: Int = 23){
    val pair: Pair<String, Int>
        get() = Pair("person_age", age)
    //Alternatively, if you don't want to use a property:
    //fun getPair() = "person_age" to age
}
但是,如果您对非配对解决方案满意,这也适用:

data class Person (var age: Int, val string: String = "person_age")

fun example(){
    val person = Person(23)
    val (name, string) = person// Allowed! Just like with Pairs
    person.age = 25; // Also allowed
    //person.string = "something"//Not allowed
}
数据类支持n-touple解包。如果没有数据类,则需要为每个要解包的组件声明一个操作符。例如:

class Person (val string: String = "person_age", var age: Int){
    operator fun component1() = string
    operator fun component2() = age
}
但是tbh,听起来数据类解决方案就是您正在寻找的解决方案。它会将字符串锁定为初始化时使用的值,并且由于默认值及其位置,您可以使用单个定位参数初始化它*

如果要对多个类型使用同一个类,也可以使用泛型

*假设代码在Kotlin中。定位参数和默认参数在Java代码中不起作用

现在,我想要capselate实际对,并且只希望用户读取/写入对的第二个值

假设这意味着您希望第一个值是最终值,而不是第二个值,则有一些选项

如果您只希望其中一个值是可写和可读的,请不要使用一对。它不是设计用来这样使用的。一对中的所有项目都是VAL

如果您想要一对,可以这样做:

class Person(var age: Int = 23){
    val pair: Pair<String, Int>
        get() = Pair("person_age", age)
    //Alternatively, if you don't want to use a property:
    //fun getPair() = "person_age" to age
}
但是,如果您对非配对解决方案满意,这也适用:

data class Person (var age: Int, val string: String = "person_age")

fun example(){
    val person = Person(23)
    val (name, string) = person// Allowed! Just like with Pairs
    person.age = 25; // Also allowed
    //person.string = "something"//Not allowed
}
数据类支持n-touple解包。如果没有数据类,则需要为每个要解包的组件声明一个操作符。例如:

class Person (val string: String = "person_age", var age: Int){
    operator fun component1() = string
    operator fun component2() = age
}
但是tbh,听起来数据类解决方案就是您正在寻找的解决方案。它会将字符串锁定为初始化时使用的值,并且由于默认值及其位置,您可以使用单个定位参数初始化它*

如果要对多个类型使用同一个类,也可以使用泛型


*假设代码在Kotlin中。定位参数和默认参数在Java代码中不起作用。

我不建议您使用Pair。也许你可以修改它,从中继承,使用扩展函数来满足你的需要,但是为什么要尝试改变一些像Pair这样简单的东西呢?。创建自己的类以满足您的需要要容易得多,在这种情况下也更简洁:

data class MyPair<out A, B>(
    val first: A, 
    var second: B
)

val pair = MyPair("age", 1)
pair.second = 2
pair.first = 1 // error

该类具有Pair所具有的所有重要特性:第一类和第二类的泛型类型,您可以使用解构声明。

我不建议您使用Pair。也许你可以修改它,从中继承,使用扩展函数来满足你的需要,但是为什么要尝试改变一些像Pair这样简单的东西呢?。创建自己的类以满足您的需要要容易得多,在这种情况下也更简洁:

data class MyPair<out A, B>(
    val first: A, 
    var second: B
)

val pair = MyPair("age", 1)
pair.second = 2
pair.first = 1 // error

该类具有Pair所具有的所有重要特性:第一类和第二类的泛型类型,并且您可以使用解构声明。

下面介绍如何覆盖Kotlin中的getter方法

class Person {
    var age: Int = 0
       get() = if (field < 0) 0 else field 

}
该属性是直接访问的

fun main(args: Array<String>) {

    val p = Person()
    p.age = -28
    println(p.age) //0
}

下面介绍如何在Kotlin中覆盖getter方法

class Person {
    var age: Int = 0
       get() = if (field < 0) 0 else field 

}
该属性是直接访问的

fun main(args: Array<String>) {

    val p = Person()
    p.age = -28
    println(p.age) //0
}
为什么不使用var-age:Int并在需要时将person\u-age返回到age?为什么不使用var-age:Int并在需要时将person\u-age返回到age?