Kotlin: 大有用途的拓展函数

先看一下拓展函数的语法结构,如下:

fun ClassName.methodName (param1:Int ,param2:Int) :Int {
    
    
  return 0
}

相比于定义一个普通函数,定义拓展函数只需要在函数名的前面加上一个ClassName. 的语法结构,就表示将该函数添加到指定类当中了.

我们再回过头看一下什么是拓展函数?

拓展函数表示即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数.

为了更好理解拓展函数,我们以以下功能为例.

一个字符串中可能包含字母、数字和特殊符号等字符,现在我们希望统计字符串中字母的数量,你要怎么实现这个功能呢?如果按照一般的编程思维,可能大多数人会很自然地写出如下函数:

object StringUtil {
    
    
   fun lettersCount(str: String): Int {
    
    
         var count = 0
         for (char in str) {
    
    
            if (char.isLetter()) {
    
    
                count++
            }
         }
        return count
   }
}

这里先定义了一个StringUtil单例类,然后在这个单例类中定义了一个lettersCount() 函数,该函数接收一个字符串参数.在lettersCount()方法中,我们使用for-in 循环去遍历字符串中的每一个字符.如果该字符串是一个字母的话,那么就将计数器加1,最终返回计数器的值.

  val str = "ABC123xyz!@#"
  val count = StringUtil.lettersCount(str)
  System.out.println(count)

这种写法绝对可以正常工作,并且这也是Java编程中最标准的实现思维.但是有了拓展函数之后就不一样了,我们可以使用一种更加面向对象的思维来实现这个功能,比如说将lettersCount() 函数添加到String类当中.

由于我们希望向String类中添加一个拓展函数,因此需要先创建一个String.kt 文件. 文件名虽然并没有固定的要求,但是我建议向哪个类添加拓展函数,就定义一个同名的Kotlin文件,这样便于你以后查找.当然,拓展函数也是可以定义在任何一个现有类当中的,并不一定非要创建新文件. 不过通常来说,最好将它定义成顶层方法,这样可以让拓展函数拥有全局的访问域.

通过对比我们可以发现,我们将lettersCount( ) 方法定义成了String类的拓展函数,那么函数就自动拥有了String实例的上下文.因此lettersCount( ) 函数就不再需要接收一个字符串参数了, 而是直接遍历this即可,因为现在this就代表着字符串本身.

根据上面拓展函数的写法, 编写如下:

fun String.lettersCount(): Int {
    
    
    var count = 0
    for (char in this) {
    
    
        if (char.isLetter()) {
    
    
            count++
        }
    }
    return count
}

定义好了拓展函数之后,统计某个字符串中的字母数量只需要这样写即可:

 val count = "ABC123xyz!@#".lettersCount()

是不是很神奇? 看上去就好像是String类中自带了lettersCount() 方法一样.

拓展函数在很多情况下让API变得更加简洁、丰富,更加面向对象.我们再次以String类为例,这是一个final类,任何一个类都不可以继承它,也就是说它的API只有固定的那些而已,至少在Java中就是如此.然而到了Kotlin中就不一样了,我们可以向String类中拓展任何函数, 使它的API变得更加丰富.

当然,拓展函数的范围,不光是String类一种,你还可以向任何类中添加拓展函数. Kotlin对此基本没有限制.如果你能利用好拓展函数这个功能,将会大幅度地提升你的代码质量和开发效率.

猜你喜欢

转载自blog.csdn.net/gaolh89/article/details/107846848