Kotlin 简明教程

Kotlin - Extensions

Kotlin扩展提供了一种通过类扩展新功能的能力,无需通过类实现继承概念或使用装饰器之类的设计模式。基本上,这些扩展在不扩展类的情况下向现有类添加一些功能。

Kotlin扩展允许为第三方库中的类编写新函数,而无需修改该类。扩展函数的优点在于,它们可以像原始类的操作一样以通常的方式调用,而这些新函数被称为 Extension Functions

同样,我们还可以为现有的Kotlin类定义 extension properties

Extension Function

Kotlin扩展函数是类的成员函数,在类外定义。创建的扩展函数在该类内作为常规函数使用。

Syntax

以下是定义 extension function 的语法。此处,扩展函数使用类名和方法名进行声明。

fun <class_name>.<method_name>(){
 ....
 function body
}

Example

在函数扩展中,Kotlin允许在主类的外部定义一个方法。在以下示例中,我们将了解如何在函数级别实现扩展。

class Alien {
   var skills : String = "null"

   fun printMySkills() {
      print(skills)
   }
}
fun main(args: Array<String>) {
   var  a1 = Alien()
   a1.skills = "JAVA"
   //a1.printMySkills()

   var  a2 = Alien()
   a2.skills = "SQL"
   //a2.printMySkills()

   var  a3 = Alien()
   a3.skills = a1.addMySkills(a2)
   a3.printMySkills()
}
fun Alien.addMySkills(a:Alien):String{
   var a4 = Alien()
   a4.skills = this.skills + " " +a.skills
   return a4.skills
}

在以上示例中,“Alien”类内没有名为“addMySkills()”的方法,不过,我们在类的外部的其他位置实现了相同的方法,这就是扩展的妙处。

当你运行上述 Kotlin 程序时,它将生成以下输出:

JAVA SQL

Extended Library Classes

Kotlin允许扩展标准库类和自定义类。例如,如果您需要一个专门用于标准Kotlin String类的函数,该函数会返回字符串中可用元音的数量,String类中尚未提供此类方法,但可以使用 extension function 完成此任务。

fun main(args: Array<String>) {
   val str = "Good morning Kotlin"

   val result = str.countVowels()
   println("Number of vowels: $result")
}
fun String.countVowels(): Int{
   var vowels = 0
   for (i in 0.. this.length - 1) {
      val ch = this[i]
      if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
         ++vowels
      }
   }
   return vowels;
}

当你运行上述 Kotlin 程序时,它将生成以下输出:

Number of vowels: 6

Companion Object Extensions

Kotlin提供了另一种机制来实现Java的静态功能。这可以通过在类中声明并用 companion 关键字标记的 companion object 来实现。使用此机制,我们可以在工厂方法中创建类的对象,之后我们只需使用类名的引用调用该方法。

在以下示例中,我们将创建一个“伴随对象”。

fun main(args: Array<String>) {
   println("Heyyy!!!"+A.show())
}
class A {
   companion object {
      fun show():String {
         return("You are learning Kotlin from TutorialsPoint.com")
      }
   }
}

当你运行上述 Kotlin 程序时,它将生成以下输出:

Heyyy!!! You are learning Kotlin from TutorialsPoint.com

以上示例看起来像Java中的静态,但是在实际时间中,我们正在创建对象作为同一类中的成员变量。这就是它也包含在扩展属性下并且还可以称为对象扩展的原因。您基本上是在扩展同一类的对象以使用某些成员函数。

Extension with Nullable Receiver

Kotlin允许使用可为空的类类型定义 Extension Functions 。可以在可为空的对象变量上调用这些扩展函数。

要为可为空的接收器定义扩展,我们只需要在扩展函数内添加一个用于可为空的接收器的检查即可,并返回适当的值。

fun main(args: Array<String>) {
   var str1 = "Good morning Kotlin"
   var str2 : String? = null

   var result = str1.countVowels()
   println("Number of vowels in str1 : $result")

   result = str2.countVowels()
   println("Number of vowels in str2 : $result")
}
fun String?.countVowels(): Any{
   if (this == null) return "null"

   var vowels = 0
   for (i in 0.. this.length - 1) {
      val ch = this[i]
      if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
         ++vowels
      }
   }
   return vowels;
}

当你运行上述 Kotlin 程序时,它将生成以下输出:

Number of vowels in str1 : 6
Number of vowels in str2 : null

Extension Properties

Kotlin允许以与我们定义扩展函数非常类似的方式定义 extension properties 。扩展属性也在类的外部定义。由于扩展实际上不会向类中插入成员,因此扩展属性没有后备字段的有效方法。这就是扩展属性不允许初始值的原因。

我们可以在属性上添加getter和setter,这些getter和setter只是扩展函数。

class Temperature(var celsius: Float)

fun main(args: Array<String>) {
   val t = Temperature(40f)
   println(t.fahrenheit)

   t.fahrenheit = 85f
   println(t.celsius)
}
var Temperature.fahrenheit: Float
    get() = (celsius * 9 / 5) + 32
    set(value) {
        celsius = (value - 32) * 5 / 9
    }

当你运行上述 Kotlin 程序时,它将生成以下输出:

104.0
29.444445