Kotlin入门(10)七十二变的输入参数
上一篇文章介绍了Kotlin对函数的基本用法,包括函数的定义、输入参数的声明、输出参数的声明等等,这些足够对付简单的场合了。当然了,倘若一门新语言仅仅满足于这些雕虫小技,那也实在没什么前途。既然Kotlin志在取代Java,就必须练成Java所不具备的功夫。本篇文章便从函数的输入参数着手,谈谈Kotlin对输入参数的改进与增强之处。
首先复习一下如何声明函数的输入参数,比如回答“中国的伟大发明有哪些?”这个问题,需要定义一个函数,根据输入的几个发明名称,然后将这几个发明拼接成完整的答案。具体的函数定义举例如下:
1 2 3 4 | fun getFourBig(general:String, first:String, second:String, third:String, fourth:String):String { var answer:String = "$general:$first,$second,$third,$fourth" return answer } |
该函数的目的是获取中国四大发明的回答,你可以输入中国古代的四大发明,也可以输入外国留学生票选的中国现代四大发明。两种输入对应的函数调用都很简单,只消按照参数顺序依次输入四大发明的名称即可,调用代码如下所示:
1 2 3 4 5 | var isOdd = true //如果从初始赋值中能够知道变量类型,就无需显式指定该变量的类型 btn_input_manual.setOnClickListener { tv_four_answer.text = if (isOdd) getFourBig( "古代的四大发明" , "造纸术" , "印刷术" , "火药" , "指南针" ) else getFourBig( "现代的四大发明" , "高铁" , "网购" , "移动支付" , "共享单车" ) isOdd = !isOdd } |
可是这么做不够智能,因为中国古代的四大发明人尽皆知,小学生都知道,何必还得每次都手工输入呢?于是Kotlin引入了默认参数的概念,允许在定义函数时直接指定输入参数的默认值,如果调用函数时没有给出某参数的具体值,系统就自动对该参数赋予默认值,从而免去了每次都要手工赋值的麻烦。默认参数的写法也很简单,只需在声明输入参数时在其后面加上等号与默认值,代码如下所示:
1 2 3 4 | fun getFourBigDefault(general:String, first:String= "造纸术" , second:String= "印刷术" , third:String= "火药" , fourth:String= "指南针" ):String { var answer:String = "$general:$first,$second,$third,$fourth" return answer } |
有了默认参数,这下函数调用简单多了,就算开发者一时脑袋浆糊想不起来四大发明,也能毫无压力轻敲代码。不信请看下面的调用代码:
1 | btn_input_default.setOnClickListener { tv_four_answer.text=getFourBigDefault( "古代的四大发明" ) } |
如果不满意参数的默认值,可在调用函数时输入新的值,例如四大发明的默认值不包含它们的发明者,现在想增加显示造纸术的发明者蔡伦,则调用getFourBigDefault函数于第二个参数填写符合要求的描述文字,代码示例如下:
1 | btn_input_part.setOnClickListener { tv_four_answer.text=getFourBigDefault( "古代的四大发明" , "蔡伦发明的造纸术" ) } |
有时想要改写的参数并不位于默认参数的第一个,比如第二个参数的“印刷术”,虽然印刷术起源于中国是毫无疑义的,但是韩国声称是他们的古人发明了金属活字印刷,德国也有确凿证据证明是古腾堡发明了活字印刷机,这些言论容易误导外人以为中国只是发明了雕版印刷术而已,事实上不光雕版印刷的发明属于中国,就连活字印刷都是北宋的毕昇发明的,所以为了正本清源,“印刷术”的名称可改为影响力更大的“活字印刷”。然而“印刷术”在函数声明里面排在“造纸术”后面,莫非要给“印刷术”改名,还得把前面的“造纸术”照抄一遍?为了解决这个不合理的地方,Kotlin又引进了命名参数的概念,说的是调用函数时可以指定某个参数的名称与数值,形如“参数名=参数值”这样。就前述的“印刷术”改名而言,具体到编码上面,可参见以下的例子:
1 | btn_input_name.setOnClickListener { tv_four_answer.text=getFourBigDefault( "古代的四大发明" ,second= "活字印刷" ) } |
默认参数结合命名参数的写法,至此告一段落。不料吃瓜群众有话说,咱们中国历史悠久、地大物博,伟大发明何止四大发明呢?譬如丝绸、瓷器、茶叶,每个拎出来都是响当当的物件,其地位在古代西方人眼里,好比现代中国人爱买的LV、劳力士、欧莱雅。所以中国的伟大发明可不能只限于四大发明,必须改成允许随时添加的,想加几个就加几个。这种随时添加对应于程序的可变参数,在Java体系中,可变参数采用“Object... args”的形式;在Kotlin体系中,新增了关键字vararg表示其后的参数个数是不确定的。以可变的字符串参数为例,Java的写法为“String... args”,而Kotlin的写法为“vararg args: String?”,具体解析的时候,则把可变参数当作一个数组,循环取出每个参数值进行处理,相应的Kotlin代码如下所示:
1 2 3 4 5 6 7 | fun getFourBigVararg(general:String, first:String= "造纸术" , second:String= "印刷术" , third:String= "火药" , fourth:String= "指南针" , vararg otherArray: String?):String { var answer:String = "$general:$first,$second,$third,$fourth" for (item in otherArray) { answer = "$answer,$item" } return answer } |
这样好了,同一个函数既可以输入四大发明,还可以输出七大发明,哪天你给弄个十大发明也是允许的。下面是带有可变参数的函数调用代码:
1 2 3 4 | btn_param_vararg.setOnClickListener { tv_four_answer.text = if (isOdd) getFourBigVararg( "古代的四大发明" ) else getFourBigVararg( "古代的七大发明" , "造纸术" , "印刷术" , "火药" , "指南针" , "丝绸" , "瓷器" , "茶叶" ) isOdd = !isOdd } |
话说中国文化博大精深,除了物质上的发明,另有不少技艺上的发明,例如国画、中医、武术等等,哪个不是国之瑰宝?因此,可变参数也要支持输入这些技巧性的发明,当然为了跟物质性的发明区分开,最好分门别类,把物质性的发明分为一组,技巧性的发明一组。如此一来,可变参数就成了可变的数组参数,同样声明数组参数时也要加上vararg前缀,告诉编译器后面的数组个数是变化的。对应的函数声明代码修改如下:
1 2 3 4 5 6 7 8 9 | fun getFourBigArray(general:String, first:String= "造纸术" , second:String= "印刷术" , third:String= "火药" , fourth:String= "指南针" , vararg otherArray: Array<String>):String { var answer:String = "$general:$first,$second,$third,$fourth" for (array in otherArray) { for (item in array) { answer = "$answer,$item" } } return answer } |
对于数组形式的可变参数,进行函数调用时得按照数组输入了,示例代码如下:
1 2 3 4 | btn_param_array.setOnClickListener { tv_four_answer.text = if (isOdd) getFourBigArray( "古代的四大发明" ) else getFourBigArray( "古代的N大发明" , "造纸术" , "印刷术" , "火药" , "指南针" ,arrayOf( "丝绸" , "瓷器" , "茶叶" ),arrayOf( "国画" , "中医" , "武术" )) isOdd = !isOdd } |
总结一下,Kotlin引入了C++的默认参数概念,并加以扩展允许通过命名参数指定修改某个参数值,而Java是不存在默认参数概念的。另外,Kotlin对Java的可变参数功能进行了增强,不但支持普通类型的可变参数,而且支持数组类型的可变参数。
__________________________________________________________________________
本文现已同步发布到微信公众号“老欧说安卓”,打开微信扫一扫下面的二维码,或者直接搜索公众号“老欧说安卓”添加关注,更快更方便地阅读技术干货。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 【.NET】调用本地 Deepseek 模型