1. 扩展函数
如果我们之前是Java使用者,那么很遗憾的是,Java一直以来都不支持这个非常有用的功能。那么扩展函数是什么呢?其实扩展函数就是说在不修改某个类源码的情况下,仍然可以向该类添加新的函数。
比如我们想要统计一个字符串中字母的数量,如果没有扩展函数,那么我们就要写一个Util类,然后写一个方法,来作统计,例如:
object StringUtil{
fun lettersCount(str:String):Int{
var count = 0;
for (char in str){
if(char.isLetter()){
count++
}
}
return count
}
}
然后我们这样调用:
fun main() {
val str = "alk3r34"
val count = StringUtil.lettersCount(str)
println("count = $count")
}
//count = 4
这种写法是Java中最标准的实现思维,但是有了扩展函数,我们就可以用一种更加面向对象的思维来实现这个功能,我们可以将lettersCount这个函数,添加到String类中。下面我们来看下扩展函数的语法结构:
fun ClassName.methodName(param1: Int, param2: Int): Int {
return 0
}
相比于普通函数,我们只需要在函数名前面加一个ClassName.的语法结构就可以了,下面我们就来看下使用扩展函数,怎么去统计字符串中的数据:
fun String.lettersCount() : Int{
var count = 0
for (char in this){
if(char.isLetter()){
count++
}
}
return count
}
此处我们将lettersCount定义为String的扩展函数,那么这个函数中就自动拥有了String这个实例的上下文,因此lettersCount函数就不再需要接收一个字符串参数了,只需要直接遍历this即可,因为现在this代表字符串本身。然后我们只需要直接使用字符串来调用lettersCount方法就可以了:
fun getStringLetterCount() {
val count = "abce254*2as#".lettersCount()
println("letters count = ${count}")
}
扩展函数是不是很有趣,我们可以对任意的类进行扩展,接下来我们看一个更加有趣的语法糖,就是运算符重载。
2. 运算符重载
熟悉Java的小伙伴们都知道函数的重载,但是在kotlin中,我们可以对运算符进行重载。这么做有什么好处呢,在Java中,对于“+”号运算符,我们只有在字符串或者数字之间使用才有意义,但是我们无法让两个Student对象相加变得有意义。但是如果我们使用运算符重载,就可以让两个Student对象相加变得有意义,好比我们可以定义两个Student对象相加就说是让每个学生所持有的数本数相加。
接下来,我们先看下运算符重载的基本语法:
//重载“+”号运算符
operator fun plus(obj: Obj): Obj {
// 处理相加的逻辑
}
我们只需要在指定函数前面加上operator关键字即可,但需要注意的是,我们必须要知道这个指定函数是什么,因为不同的运算符对应的重载函数也是不同的,如“+”号对应的是plus(),"-"号对应的是minus()函数。接下来我们举例看下:
class Student(val name:String,val books:Int) {
operator fun plus(stu:Student):Student{
val sum = books + stu.books
return Student("allbooks",sum)
}
}
fun main() {
val stu1 = Student("张三",5)
val stu2 = Student("小明",3)
val allBooks = stu1 + stu2
println("allbooks = ${allBooks.books}")
}
//allbooks = 8
再比如,我们可以Money进行相加,同时我们还可以进行汇率的换算:
使用密封类定义币种
sealed class MoneyType{}
class RMB :MoneyType()
class Dollor:MoneyType()
//定义数据类Money
data class Money(val moneyType: MoneyType,val value:Int){
operator fun plus(money: Money):Money{
val sum = when(moneyType){
is RMB -> {when(money.moneyType) {
is RMB -> value + money.value
is Dollor -> value + money.value*7
}}
is Dollor -> {when(money.moneyType) {
is RMB -> value + money.value / 7
is Dollor -> value
}}
}
return Money(moneyType,sum)
}
}
fun main() {
val rmb = Money(RMB(),7)
val dollor = Money(Dollor(),7)
val dolorSum = dollor + rmb
val rmbSum = rmb + dollor
println("dolorSum = $dolorSum")
println("rmbSum = $rmbSum")
}
//dolorSum = Money(moneyType=com.liuhp.helloworld.part5.Dollor@5e481248, value=8)
//rmbSum = Money(moneyType=com.liuhp.helloworld.part5.RMB@66d3c617, value=56)
关于数据类和密封类的相关知识,请移步:Kotlin-类与对象:data数据类,object单例类,sealed密封类(第一行代码Kotlin学习笔记2).
此段代码我们先判断了当前币种,然后以当前币种为基准进行换算。不熟悉when语句的同学,请移步:Kotlin-变量var,val,${}和函数when,for-in(第一行代码Kotlin学习笔记1).
运算符重载对照表(复制于第一行代码随书ppt)
我们上面只说了“+”号的重载函数puls(),其实我们可以用运算符重载实现很多好玩儿的功能。剩下的就请秀发茂密的童鞋们自行探索吧。