Kotlin - 扩展


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

Kotlin 扩展允许为第三方库中的类编写新函数,而无需修改该类。扩展函数的美妙之处在于它们可以以通常的方式调用,就好像它们是原始类的方法一样,这些新函数称为扩展函数

同样,我们也可以为现有的 Kotlin 类定义扩展属性。

扩展功能

kotlin 扩展函数是类的成员函数,在类外部定义。创建的扩展函数在该类中用作常规函数。

句法

以下是定义扩展函数的语法。这里,扩展函数是使用类名和方法名来声明的。

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

例子

在函数扩展中,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

扩展库类

Kotlin 允许扩展标准库类以及用户定义的类。例如,如果您需要标准 Kotlin String 类的专用函数来返回字符串中可用元音的数量,此类方法在 String 类中尚不可用,但您可以使用扩展函数来完成此任务

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

伴随对象扩展

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

在下面的示例中,我们将创建一个“伴生对象”。

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 中看起来像是静态的,但是,我们实时创建一个对象作为同一类的成员变量。这就是为什么它也包含在扩展属性下,并且可以称为对象扩展。您基本上是在扩展同一类的对象以使用某些成员函数。

带有可为空接收器的扩展

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

要定义 Nullable 接收器的扩展,我们只需在扩展函数内添加对 null 接收器的检查,然后返回适当的值。

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

扩展属性

Kotlin 允许以与我们定义扩展函数非常相似的方式定义扩展属性。扩展属性也在类外部定义。由于扩展实际上并不将成员插入到类中,因此没有有效的方法让扩展属性具有支持字段。这就是扩展属性不允许初始值设定项的原因。

我们可以添加 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

测验时间(面试和考试准备)

答案:A

解释

Kotlin 扩展函数在类外部定义,不会影响现有功能。

答案:D

解释

关于扩展属性的所有陈述都是正确的。