📜  Kotlin 扩展函数

📅  最后修改于: 2022-05-13 01:55:36.113000             🧑  作者: Mango

Kotlin 扩展函数

Kotlin 使程序员能够向现有类添加更多功能而无需继承它们。这是通过称为扩展的功能实现的。当一个函数被添加到一个现有的类中时,它被称为扩展函数。要将扩展函数添加到类,请定义一个附加到类名的新函数,如以下示例所示:

Kotlin
package kotlin1.com.programmingKotlin.chapter1
 
// A sample class to demonstrate extension functions
class Circle (val radius: Double){
    // member function of class
    fun area(): Double{
        return Math.PI * radius * radius;
    }
}
fun main(){
    // Extension function created for a class Circle
    fun Circle.perimeter(): Double{
        return 2*Math.PI*radius;
    }
    // create object for class Circle
    val newCircle = Circle(2.5);
    // invoke member function
    println("Area of the circle is ${newCircle.area()}")
    // invoke extension function
    println("Perimeter of the circle is ${newCircle.perimeter()}")
}


Kotlin
fun main(){
 
    // Extension function defined for Int type
    fun Int.abs() : Int{
        return if(this < 0) -this else this
    }
 
    println((-4).abs())
    println(4.abs())
}


Kotlin
// Open class created to be inherited
open class A(val a:Int, val b:Int){
}
 
// Class B inherits A
class B():A(5, 5){}
 
fun main(){
     
    // Extension function operate defined for A
    fun A.operate():Int{
        return a+b
    }
 
    // Extension function operate defined for B
    fun B.operate():Int{
        return a*b;
    }
 
    // Function to display static dispatch
    fun display(a: A){
        print(a.operate())
    }
 
    // Calling display function
    display(B())
}


Kotlin
// A sample class to display name name
class AB(val name: String){
    override fun toString(): String {
        return "Name is $name"
    }
}
 
fun main(){
    // An extension function as a nullable receiver
    fun AB?.output(){
        if(this == null){
            println("Null")
        }else{
            println(this.toString())
        }
    }
 
    val x = AB("Charchit")
     
    // Extension function called using an instance
    x.output()
    // Extension function called on null
    null.output()
}


Kotlin
class MyClass {
    // companion object declaration
    companion object {
        fun display(){
            println("Function declared in companion object")
        }
    }
}
fun main(args: Array) {
   // invoking member function
   val ob = MyClass.display() 
}


Kotlin
class MyClass {
    companion object {
        // member function of companion object
        fun display(str :String) : String{
            return str
        }
    }
}
    // extension function of companion object
fun MyClass.Companion.abc(){
    println("Extension function of companion object")
}
fun main(args: Array) {
    val ob = MyClass.display("Function declared in companion object")
    println(ob)
    // invoking the extension function
    val ob2 = MyClass.abc()
}


输出:

Area of the circle is 19.634954084936208
Perimeter of the circle is 15.707963267948966

解释:

在这里,使用类Circle.perimeter()的点表示法将一个新函数附加到类,它的返回类型是 Double。在 main函数中,创建了一个对象来实例化 Circle 类,并在println()语句中调用该函数。调用成员函数时,它返回圆的面积,类似地,扩展函数返回圆的周长。

使用扩展函数的扩展库类

Kotlin 不仅允许扩展用户定义的类,还可以扩展库类。扩展函数可以添加到库类中,并以与用户定义类类似的方式使用。以下示例演示了为库类创建的扩展函数-

科特林

fun main(){
 
    // Extension function defined for Int type
    fun Int.abs() : Int{
        return if(this < 0) -this else this
    }
 
    println((-4).abs())
    println(4.abs())
}

输出:

4
4

说明:在这里,我们使用扩展函数。我们对整数值执行取模运算。我们传递了整数值 -4 和 4 并获得了两者的正值。如果参数值小于 0,则返回 -(value),如果参数值大于零,则返回相同的值。

扩展是静态解析的

关于扩展函数需要注意的一点是它们是静态解析的,即执行哪个扩展函数完全取决于调用它的表达式的类型,而不是取决于在运行时最终执行表达式时解析的类型.以下示例将使上述论点清楚:

科特林

// Open class created to be inherited
open class A(val a:Int, val b:Int){
}
 
// Class B inherits A
class B():A(5, 5){}
 
fun main(){
     
    // Extension function operate defined for A
    fun A.operate():Int{
        return a+b
    }
 
    // Extension function operate defined for B
    fun B.operate():Int{
        return a*b;
    }
 
    // Function to display static dispatch
    fun display(a: A){
        print(a.operate())
    }
 
    // Calling display function
    display(B())
}

输出:

10

解释:

如果您熟悉Java或任何其他面向对象的编程语言,您可能会注意到在上面的程序中,由于类 B继承了类 A并且传递的参数 display函数是类 B的一个实例。根据动态方法 dispatch的概念,输出应该是25 ,但是由于扩展函数是静态解析的,所以在类型 A 上调用操作函数。因此输出是 10。

可空接收器

扩展函数也可以用可以为null的类类型来定义。在这种情况下,当在扩展函数中添加对 null 的检查并返回适当的值时。
作为可空接收器的扩展函数示例 –

科特林

// A sample class to display name name
class AB(val name: String){
    override fun toString(): String {
        return "Name is $name"
    }
}
 
fun main(){
    // An extension function as a nullable receiver
    fun AB?.output(){
        if(this == null){
            println("Null")
        }else{
            println(this.toString())
        }
    }
 
    val x = AB("Charchit")
     
    // Extension function called using an instance
    x.output()
    // Extension function called on null
    null.output()
}

输出:

Name is Charchit
Null

伴随对象扩展

如果一个类包含一个伴生对象,那么我们也可以为伴生对象定义扩展函数和属性。伴随对象声明——

科特林

class MyClass {
    // companion object declaration
    companion object {
        fun display(){
            println("Function declared in companion object")
        }
    }
}
fun main(args: Array) {
   // invoking member function
   val ob = MyClass.display() 
}

输出:

Function declared in companion object

就像调用伴生对象的常规成员函数一样,扩展函数可以只使用类名作为限定符来调用。伴随对象扩展示例 –

科特林

class MyClass {
    companion object {
        // member function of companion object
        fun display(str :String) : String{
            return str
        }
    }
}
    // extension function of companion object
fun MyClass.Companion.abc(){
    println("Extension function of companion object")
}
fun main(args: Array) {
    val ob = MyClass.display("Function declared in companion object")
    println(ob)
    // invoking the extension function
    val ob2 = MyClass.abc()
}

输出:

Function declared in companion object
Extension function of companion object