用Kotlin实现变量联动

2020-12-01 03:17刘华煜
电脑知识与技术 2020年29期

摘要:变量联动指的是一个变量发生变化,其他变量也会发生变化。用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-),男,讲师,硕士,研究方向为计算机应用。