摘要:变量联动指的是一个变量发生变化,其他变量也会发生变化。用Kotlin可以在语言层面实现变量联动。
关键词:变量联动;Kotlin;Getter;Setter
中图分类号:TP311 文献标识码:A
文章编号:1009-3044(2020)29-0214-03
1 背景
在编写程序的过程中,为了逻辑上的统一,经常需要一个变量的值发生变化,另一个变量的值也要产生变化,反之亦然。这两个变量就属于联动关系。
很多语言难以从语言层面实现这个功能,只能每次改变其中一个变量值的时候同时用代码改变另一个变量值,这样就显得很哕唆。而Kotlin作为现代语言,就可以在语言层面实现这个功能。
2 变量联动
编程时经常一个变量的值发生变化,另一个变量的值也要变化。比如有三个变量表达一个人的姓、名和姓名,当姓发生变化时,姓名也要发生变化:
String xing,ming,xingming;
xmg=”张”;
xmgmmg=xing+ming;
如果更改过于频繁,可以把这两条语句提炼成一个方法,更改姓的时候同时更改姓名,然后在需要更改姓的时候调用这个方法就可以了。
然而更改名的时候也要更改姓名,那么就需要另一个方法在更改名的时候同时更改姓名。如果直接更改姓名,还需要一个方法在更改姓名的时候把姓名分割,然后更改姓和名两个变量。
这样就需要3个方法来实现变量联动,显得很烦琐。而Kotlin就可以很优雅地实现这个功能。
3 Kotlin简介
Kotlin由JetBrains公司开发,如今Kotlin已经支持Android开发,并提供了一系列的Android开发插件。它是一门静态语言,支持多种平台,包括移动端、服务端以及浏览器端,此外,Kotlin还是一门融合了面向对象与函数式编程的语言,支持泛型、安全的空判断,并且Kotlin与Java可以做到完全的交互。
4 Getter与Setter
Kotlin可以通过Getter在读取变量时做出干预。如:
var test:String=””
get0=”aaa”
其中get()就是Getter,读取test变量所得到的是这个方法的返回值。那么
fun main(args:Array
test="123"
print(test)
)
的结果是输出aaa,虽然test的真正值是123。
同樣,Kotlin可以通过Setter在给变量赋值时做出干预。如:
var test:String2””
set(value){field=”aaa'}
其中set0就是Setter,value是被赋的值,field称为后备字段,它代表test真正的值。那么
fun main(args:Array
test="123"
print(test)
)
的结果是输出aaa,虽然感觉上test被赋值成123,但在Set-ter中field被赋值成aaa,那么test的值就是aaa。
Setter经常被用于预处理所赋的值,如表达分数的值不能是负数:
var score=0
set(value){field= if(value <0)0 else value}
fun main(args: Array
score=8
print(score)
score=-5
print(score)
}
的结果是80,虽然score第二次被赋值成-5,但在set方法中由于value的值是-5,小于0,然后field被赋值成0,所以score的真正的值是0。
需要注意的是在Getter与Setter中必须用field,不能用变量名,否则会陷入死循环。另外因为val修饰的变量是只读变量,所以val变量不能有Setter。
5 用Getter或Setter实现简单的变量联动
如果要让变量a2是变量a的两倍,可以用如下代码实现:
classtf
var a=0
var a2=0
getO=a*2
)
fun main(args: Array
var x=t0
x.a=4
print(x.a2)
)
会输出8,保证了a2是a的二倍。但如果给a2赋值,a的值却不会自动变成a2的一半。
也可以用Setter处理这个问题,代码如下:
classtf
var a=0
set(value){
field=value
a2=a*2
)
var a2=0
)
同样,如果给a2赋值,a的值不会自动变成a2的一半。
6 用Setter实现姓名变量联动
对姓名问题而言,可以这样写xmg和nung的Setter:
class xmf
var xing:String=””
set(value){
field=value
xingming=value+ming
)
var ming:String= " "
set(value) [
field=value
xingming=xing+value
)
var xingming:String=””
)
fun main(args: Array
var x=xm0
x.xing=”张
x.rmng=”強”
print(x.xingming)
)
输出的结果是张强,虽然没有明确给xmgming赋值,但在xing和rmng的Setter中却给xingming赋值了,这样就保证了3个变量的逻辑上的一致性。
对于xmgmmg的Setter,稍显复杂,因为它要给xmg和mmg两个变量赋值:
var xingming:String=
set(value) {
field=value
xing=value.substring(0,1)
ming=value.substring(l,value.length)
)
这样的话
fun main(args: Array
var x=xm()
x.xingming=”张强”
print(x.xing+”一一”+x.ming)
)
的结果就是张一强,把xing和mmg分开了。
需要注意的是,xingming的Setter不能和xing或ming的Set-ter -同出现,因为在xingming的Setter中会修改xing/ming,从而调用xing/ming的Setter,而xing/ming的Setter中会修改xing-rmng,从而调用xmgming的Setter,这样就会陷入死循环。
所以这不是一个完美的方案。
7 用Getter实现姓名变量联动
对姓名问题而言,可以这样写xmgming的Getter:
class xmf
var xing:String="
var ming:String=“”
var xingming:String=””
getO=xing+ming
)
这样
fun main(args: Array
var x=xm0
x.xmg=”张”
x.ming=”强”
print(x.xingming)
)
的结果是张强,实现了变量联动。
xing和rmng的Getter可以这样写:
class xmf
var xing:String=””
getO=xingming.substring(0,1)
var ming:String=””
getO=xingming.substring(l,xingming.length)
var xingming:String=””
)
fun main(args: Array
var x=xm()
x.xlrWnmg=”张强”
print(x.xing+”一一”+x.ming)
)
结果是张一强,把xing和rmng分开了。
但需要注意的是,和Setter -样,xingming的Getter不能和xmg或rmng的Getter -同出现,理由也类似:会造成死循环。
8 混用Getter和Setter实现姓名变量联动
单纯用Getter或Setter都无法完美实现姓名变量联动,混用却可以实现:
class xmf
var xing:String=…
var ming:String=””
var xingming:String="
getO=xing+ming
set(value){
field=value
xing=value.substring(0,1)
ming=value.substring(l,value.length)
)
)
通过只使用xmgrmng的Getter和Setter就可以完美实现姓名变量的联动。
fun main(args: Array
var x=xmQ
x.xmgrning=”张强”
print(x.xing+”一一”+x.ming)
x.xmg=”王”
print(x.xingming)
}
会输出张一一强一王强。
另一种方法是使用xmg和ming的Getter和Setter实现姓名变量的联动,原理类似,但更加复杂。
9 并联电阻的电压电流问题
电压、电流、电阻之间也有联动关系,具体地说是电压=电流×电阻。假设现在有两个电阻并联,需要解决的是两个电阻值和总电流、总电压的关系。这里假设电流不可主动赋值。
用Setter解决问题的代码如下:
var U:Double=0.0
set(v){field=v;I=U/R1+U/R2)
var Rl:Double=l.0
set(v){field=v;I=U/R1+U/R2)
var R2:Double=l.0
set(v){field=v;I=U/R1+U/R2)
var I:Double=0.0
可以看出无论改变R1、R2、U中的哪一个,都会重新计算电流的值。
fun main(args:Array
U=4.0
R1=2.0
R2=1.0
print(I.toString0+”一一”)
U=6.0
print(l)
)
的结果是6.0-9.0,解决了变量联动问题。
用Getter解决问题的代码如下:
var U:Double=0.0
var Rl:Double=0.0
var R2:Double=0.0
val R:Double
getO=U/I
val Il:Double
getO=U/R1
val I2:Double
getO=U/R2
val I:Double
get0=11+12
可以看出,Getter方式可以求出更多的东西:RI的电流II、R2的电流12以及总电阻R,如果用Setter方式求这些,则要多出很多代码。
10 结束语
用Kotlin的Getter和Setter可以优雅地解决变量联动问题,在实战的时候需要注意变量的Getter和Setter的死循环问题,另外在绝大多数场合,Getter比Setter更加方便。
参考文献:
[1]水滴技术团队.Kotlin核心编程[M].北京:机械工业出版社,2019.
[2]封亚飞.揭秘Kotlin编程原理[M].北京:电子工业出版社,2018.
[3] Saumont P-Y.Kotlin编程之美.機械工业出版社[M].北京:机械工业出版社,2020.
【通联编辑:谢媛媛】
作者简介:刘华煜(1976-),男,讲师,硕士,研究方向为计算机应用。