Kotlin知识归纳(三) —— 顶层成员与扩展

栏目: Java · 发布时间: 6年前

Kotlin知识归纳(一) —— 基础语法

Kotlin知识归纳(二) —— 让函数更好调用

Kotlin知识归纳(三) —— 顶层成员与扩展

Java 项目中,多多少少都存在以Utils结尾的Java类。其内部并无任何状态和实例函数,只有一堆与该名称相关的静态属性或静态方法。该类只是作为一种容器存储着静态属性和静态方法。

顶层函数

Kotlin认为,根本不需要创建这些无意义的类。可以直接将函数放在代码文件的顶层,不用附属于任何一个类。

在com.daqi包中的daqi.kt文件中定义顶层函数joinToString()

package com.daqi

@JvmOverloads
fun <T> joinToString(collection: Collection<T>,
                      separator:String = ",",
                      prefix:String = "",
                      postfix:String = ""):String{
    val result = StringBuilder(prefix)
    for ((index,element) in collection.withIndex()){
        if (index > 0)
            result.append(separator)
        result.append(element)
    }
    result.append(postfix)
    return result.toString()
}
复制代码

在Kotlin中,顶层函数属于包内成员,包内可以直接使用,包外只需要import该顶层函数,即可使用。

Kotlin和Java具有很强互操作性,如果让Java调用顶层函数该怎么调用呢?先看一下顶层函数编译成Java是什么样的:

public final class DaqiKt {
   @NotNull
   public static final String joinToString(Collection collection, String separator,
                    String prefix,String postfix) {
   }
}
复制代码

编译器将顶层函数所在的文件名daqi.kt作为类名DaqiKt,生成对应的类文件。该kt文件下的所有顶层函数都编译为这个类的静态函数。

so,如果在Java中调用Kotlin的顶层函数时,需要对其的文件名转换为对应的类名,再进行调用。

DaqiKt.joinToString(new ArrayList<>(),"",",","");
复制代码

如果想规定kt文件转换为Java类时的类名,可以使用@file:JvmName()注解进行修改。将其放在文件的开头,位于包名之前:

@file:JvmName("StringUtils")
package com.daqi

fun <T> joinToString(...){
	...
}
复制代码

就可以使用特定的类名在Java中调用对应的顶层函数。

StringUtils.joinToString(new ArrayList<>(),"",",","");
复制代码

顶层属性

既然有顶层方法,应该也有顶层属性。和顶层函数一样,属性也可以放在文件的顶层,不附属与任何一个类。这种属性叫顶层属性。

@file:JvmName("StringUtils")
package com.daqi

val daqiField :String = "daqi"
复制代码

顶层属性和其他任意属性一样,都提供对应的访问器(val 变量提供getter,var 变量提供getter 和 setter)。也就是说,当Java访问该顶层属性时,通过访问器进行访问的。

StringUtils.getDaqiField();
复制代码

通过反编译查看其转换为Java的样子:

@NotNull
private static final String daqiField = "daqi";

@NotNull
public static final String getDaqiField() {
    return daqiField;
}
复制代码

顶层属性被定义为 私有的 静态对象,并配套了一个静态访问器方法。

如果需要定义 public 的静态变量,可以用 const关键字 修饰该变量。(仅适用于基础数据类型和String类型的属性)

在反编译的文件中可以看到,静态属性变成public,且没有了具体的静态访问器。

//Kotlin
const val daqiField :String = "daqi"

//Java
public static final String daqiField = "daqi";
复制代码

扩展函数

Kotlin可以在无需继承的情况下扩展一个类的功能,然后像内部函数一样直接通过对象进行调用。扩展函数这个新特可以很平滑与现有Java代码进行集成。

声明一个扩展函数,需要用一个 接收者类型 也就是被扩展的类型来作为他的前缀。而调用该扩展函数的对象,叫作 接收者对象 。接收者对象用this表示,this可有可无。

fun String.lastChar():Char{
    return this.get(this.length - 1)
}

//调用扩展函数
"daqi".lastChar()
复制代码

扩展函数的可见性

在扩展函数中,可以直接访问被扩展类的方法和属性。但扩展函数不允许你打破对象的封装性,扩展函数不能访问 private 的成员。具体什么意思呢,先定义一个java类:

public class daqiJava {
    private String str = "";
    public String name = "";

    public void daqi(){
    }

    private void daqi(String name){
    }
}
复制代码

对其该类进行扩展:

Kotlin知识归纳(三) —— 顶层成员与扩展

public的方法可以正常访问,但凡用 private 修饰的属性或方法,无法在扩展函数中被调用。

Java调用扩展函数

回到Kotlin和Java交互性的问题,Java如何调用扩展函数的呢?这时候又要一波反编译:

public static final void extensionMethod(daqiJava $receiver,String string) {
    
}
复制代码

扩展函数daqiJava#extensionMethod()被转换为一个相同名称的 静态函数 。函数 第一个参数变成接受者类型 ,后面才是原函数的参数列表。

扩展是静态解析的

在JVM语言的多态中,被重写方法的调用依据其调用对象的实际类型进行调用。但扩展函数是静态分发的,即意味着扩展函数是由其所在表达式中的调用者的类型来决定的。

我们都知道Button是View的子类,同时为View和Button定义名为daqi的扩展函数。

val view:View = Button()
view.daqi()
复制代码

此时调用的是View的扩展函数,即使它实质是一个Button对象。因为扩展函数所在的表达式中,view是View类型,而不是Button类型。

扩展函数其他特性

  • 扩展函数与顶层函数类似,在Java层进行调用时,依据其所在的文件名作为类名,其作为静态函数,存储在该类中。(也支持@file:JvmName("")进行)

  • 在扩展函数中,除了可以调用接受者类型的成员函数和成员属性外,还可以调用该类的扩展函数。

  • 如果一个类的成员函数与扩展函数拥有相同的方法签名,成员函数会被优先使用。

  • 扩展函数其实是静态函数,扩展函数不能被子类重写。但子类仍可以调用父类的扩展函数。

扩展属性

扩展属性不能有初始化器,它们的行为只能由 显式提供 的 getters/setters 定义。因为没有地方对它进行存储,不可能给现有的Java对象实例添加额外的属性。只是用 属性的语法 对接受者类型进行扩展。

声明一个扩展常量:

val String.lastChar:Char
	get() = get(length - 1)
复制代码

声明一个扩展变量:

var StringBuffer.lastChar:Char
    get() = get(length - 1)
    set(value:Char){
        this.setCharAt(length - 1,value)
    }
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML5

HTML5

Matthew David / Focal Press / 2010-07-29 / USD 39.95

Implement the powerful new multimedia and interactive capabilities offered by HTML5, including style control tools, illustration tools, video, audio, and rich media solutions. Understand how HTML5 is ......一起来看看 《HTML5》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

SHA 加密
SHA 加密

SHA 加密工具