Kotlin 简明教程
Kotlin - Extensions
Kotlin扩展提供了一种通过类扩展新功能的能力,无需通过类实现继承概念或使用装饰器之类的设计模式。基本上,这些扩展在不扩展类的情况下向现有类添加一些功能。
Kotlin extensions provide the ability to extend a class with new functionality without implementing the inheritance concept by a class or using design pattern such as Decorator. These extensions basically add some functionality in an existing class without extending the class.
Kotlin扩展允许为第三方库中的类编写新函数,而无需修改该类。扩展函数的优点在于,它们可以像原始类的操作一样以通常的方式调用,而这些新函数被称为 Extension Functions 。
The Kotlin extension allows to write new functions for a class from a third-party library without modifying the class. The beauty of the extension functions is that they can be called in the usual way, as if they were methods of the original class and these new functions are called Extension Functions.
同样,我们还可以为现有的Kotlin类定义 extension properties 。
Similarly, we can also define extension properties for an existing Kotlin class.
Extension Function
Kotlin扩展函数是类的成员函数,在类外定义。创建的扩展函数在该类内作为常规函数使用。
A kotlin extension function is a member function of a class, which is defined outside the class. The created extension functions are used as a regular function inside that class.
Syntax
以下是定义 extension function 的语法。此处,扩展函数使用类名和方法名进行声明。
Following is the syntax to define an extension function. Here, the extension function is declared with using the class name and also with using method name.
fun <class_name>.<method_name>(){
....
function body
}
Example
在函数扩展中,Kotlin允许在主类的外部定义一个方法。在以下示例中,我们将了解如何在函数级别实现扩展。
In function extension, Kotlin allows to define a method outside of the main class. In the following example, we will see how the extension is implemented at the functional level.
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()”的方法,不过,我们在类的外部的其他位置实现了相同的方法,这就是扩展的妙处。
In the above example, we don’t have any method inside “Alien” class named as “addMySkills()”, however, we still are implementing the same method somewhere else outside of the class, This is the magic of extension.
当你运行上述 Kotlin 程序时,它将生成以下输出:
When you run the above Kotlin program, it will generate the following output:
JAVA SQL
Extended Library Classes
Kotlin允许扩展标准库类和自定义类。例如,如果您需要一个专门用于标准Kotlin String类的函数,该函数会返回字符串中可用元音的数量,String类中尚未提供此类方法,但可以使用 extension function 完成此任务。
Kotlin allows to extend the standard library classes as well as user-defined classes. For example, if you need a specialised function for standard Kotlin String class which will return the number of vowels available in the string, such method is not already available in String class but you can use an extension function to accomplish this task.
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 程序时,它将生成以下输出:
When you run the above Kotlin program, it will generate the following output:
Number of vowels: 6
Companion Object Extensions
Kotlin提供了另一种机制来实现Java的静态功能。这可以通过在类中声明并用 companion 关键字标记的 companion object 来实现。使用此机制,我们可以在工厂方法中创建类的对象,之后我们只需使用类名的引用调用该方法。
Kotlin provides another mechanism to implement static functionality of Java. This can be achieved using the companion object which is declared inside a class and marked with the companion keyword. Using this mechanism, we can create an object of a class inside a factory method and later we can just call that method using the reference of the class name.
在以下示例中,我们将创建一个“伴随对象”。
In the following example, we will create a “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 程序时,它将生成以下输出:
When you run the above Kotlin program, it will generate the following output:
Heyyy!!! You are learning Kotlin from TutorialsPoint.com
以上示例看起来像Java中的静态,但是在实际时间中,我们正在创建对象作为同一类中的成员变量。这就是它也包含在扩展属性下并且还可以称为对象扩展的原因。您基本上是在扩展同一类的对象以使用某些成员函数。
The above example seems like static in Java, however, in real-time we are creating an object as a member variable of that same class. This is why it is also included under extension property and can be alternatively called as an object extension. You are basically extending the object of the same class to use some of the member functions.
Extension with Nullable Receiver
Kotlin允许使用可为空的类类型定义 Extension Functions 。可以在可为空的对象变量上调用这些扩展函数。
Kotlin allows to define Extension Functions with a nullable class type. These extension function can be called on a nullable object variable.
要为可为空的接收器定义扩展,我们只需要在扩展函数内添加一个用于可为空的接收器的检查即可,并返回适当的值。
To define an extension for Nullable receiver, we just need to add a check for null receiver inside the extension function, and the appropriate value is returned.
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 程序时,它将生成以下输出:
When you run the above Kotlin program, it will generate the following output:
Number of vowels in str1 : 6
Number of vowels in str2 : null
Extension Properties
Kotlin允许以与我们定义扩展函数非常类似的方式定义 extension properties 。扩展属性也在类的外部定义。由于扩展实际上不会向类中插入成员,因此扩展属性没有后备字段的有效方法。这就是扩展属性不允许初始值的原因。
Kotlin allows to define extension properties in very similar way like we defined extension function. Extension properties are also defined outside of the class. Since extensions do not actually insert members into classes, there is no efficient way for an extension property to have a backing field. This is why initializers are not allowed for extension properties.
我们可以在属性上添加getter和setter,这些getter和setter只是扩展函数。
We can add getter and setter along with the property which are nothing but the extension functions.
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 程序时,它将生成以下输出:
When you run the above Kotlin program, it will generate the following output:
104.0
29.444445