假设我有以下课程:
class Person() {
var age: Pair<String, Int> = Pair("person_age", 23)
// override getValue and setValue here
}
现在,我想封装实际的Pair
,只希望用户读取/写入该对的第二个值。是否可以覆盖getValue
和setValue
方法,以便我可以执行以下操作:
val p = Person()
p.age = 25
if(p.age <= 30)
当然,我可以为每个属性编写自己的getter
和setter
方法,但是Kotlin的一件好事是,您必须编写更少的样板代码,然后这些代码会丢失。
答案 0 :(得分:1)
以下内容可能已经足够:
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
,请执行以下操作:
p.toAgePair() // or skip that method and use: '"person_age" to p.age' instead
访问Pair
内容的替代方法是:Pair.first
,Pair.second
或destructured,例如:
val myPair = Pair("person_age", 23)
// myPair.second = 25 // setting will not work however
myPair.let { (name, age) -> /* do something with it */ }
或者:
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
但是,如果我正确地理解了您的信息,那么您就可以同时访问您可能不想使用的两个值。
您可以使用自己的data class
和var
来克服设置部分,但是再次,您并不能从中真正受益。
答案 1 :(得分:1)
现在,我想对实际的货币对大写,只希望用户读取/写入货币对的第二个值。
假设这意味着您希望第一个值是最终值,而不是第二个,那么有一些选择。
如果只希望其中一个值可写和可读,请不要使用一对。它并非旨在那样使用。一对中的所有项目均为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
}
这是创建一个最终对,其中第一个值不能修改,而第二个可以修改。
所以现在:
fun example(){
val person = Person()
person.age = 25;//Fine: Age is an int, and a var
//person.pair = Pair("something", 45)//fails: "Val cannot be reassigned
val pair = person.pair // Allowed. Accessing the pair still works
assert(pair.second == person.age) // This is true
}
但是,如果您对非配对解决方案感到满意,那么它也可以工作:
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折叠。如果没有数据类,则需要为要解压缩的每个组件声明一个operator fun
。示例:
class Person (val string: String = "person_age", var age: Int){
operator fun component1() = string
operator fun component2() = age
}
但是,听起来,data class
解决方案是您正在寻找的解决方案。它将把String锁定为其初始化的对象,并且由于默认值及其位置,您可以使用单个定位参数进行初始化*
如果要将同一类用于多种类型,则也可以使用泛型。
*假定代码在Kotlin中。定位参数和默认参数不适用于Java代码。
答案 2 :(得分:1)
我完全不建议您使用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
具有的所有重要功能:first
和second
的通用类型,您可以使用解构声明。
答案 3 :(得分:1)
这是在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
}