kotlin特性之object、apply用法总结 - Xiasm/Java-Android-Learn GitHub Wiki
最近试用了下kotlin,因为也是一个在jvm执行的静态语言,所以快速熟悉了下语法就直接用了。但是用的过程中,还是有些地方花费了很长时间才理解。仅此记录下来
object是kotlin中一个很重要的关键字,java中没有。object关键字直译过来就是“对象”,object关键字用法有很多种,如对象声明、伴生对象、对象表达式等。我们先来从最简单的看:
- 对象声明
我们先来写一个object修饰的类,然后转成java代码看一下:
object Test {
fun hello() {
}
}
这是一个object修饰的类,使用object关键字后就不能再使用class关键字了。我们用as的工具将其转换为java代码如下:
public final class Test {
public static final Test INSTANCE;
public final void hello() {
}
static {
Test var0 = new Test();
INSTANCE = var0;
}
}
生成的java代码可以看出,这是一个final修饰的类,并且在加载类的时候实例化出一个对象INSTANCE,你大概隐隐猜出了这个object关键字代表着什么含义吧!
对的,如果你用object声明一个类,这个类就是一个“单例的类”。如果你在AndroidStudio中打算继承此类,会飘红报错“Cannot inherit from a singleton”,即不能继承一个单例,从java代码中也可以看出。
做下总结:object关键字声明一个类,这个类就是单例的,不能再创建实例,并且没有构造器,调用的时候有以下两种方法:
//直接类名调用
Test.hello()
//赋给一个常量,再调用
val a : Test = Test
a.hello()
- 伴生对象(Companion object)
在用kotlin的时候,我发现kotlin中没有static关键字,那么如何来表示出static的效果呢?我还以一个例子来解释:
class Test1 {
companion object CO {
val filed : String = "I'm in companion object"
fun coHello(){
println(filed)
}
}
fun hello() {
println("I'm Test1")
}
}
转成java代码后:
public final class Test1 {
@NotNull
private static final String filed = "I'm in companion object";
public static final Test1.CO CO = new Test1.CO((DefaultConstructorMarker)null);
public final void hello() {
String var1 = "I'm Test1";
System.out.println(var1);
}
@Metadata(
mv = {1, 1, 11},
bv = {1, 0, 2},
k = 1,
d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0003\n\u0002\u0010\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0007\u001a\u00020\bR\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\t"},
d2 = {"Lorg/doubleprotein/mathilda/notes/Test1$CO;", "", "()V", "filed", "", "getFiled", "()Ljava/lang/String;", "coHello", "", "app"}
)
public static final class CO {
@NotNull
public final String getFiled() {
return Test1.filed;
}
public final void coHello() {
String var1 = ((Test1.CO)this).getFiled();
System.out.println(var1);
}
private CO() {
}
// $FF: synthetic method
public CO(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
可以看得出,伴生对象类似于java中的静态内部类,并且在Test1中会持有一个伴生对象的实例,我们在调用伴生对象的方法时,有以下两种调用方式:
//方式1
Test1.CO.coHello()
//方式2
Test1.coHello()
//调用属性
Test1.filed
效果是不是跟java中调用static方法或属性很相似。当然kotlin中替代static关键字特性的东西不止半生对象一个,还有一个包级别函数也可以用来替代。
apply函数的返回值是本身,在函数内部,你可以任意调用对象的属性或方法或给属性赋值等!我们还是通过例子来看:
class People {
var eye : Int = 2
var leg : Int = 2
fun hello() {
println("eyes=" + eye + ", legs=" + leg)
}
}
定义Peoplele类,然后创建实例,并调用它的apply方法:
fun test() {
val p = People()
p.apply {
eye = 3
hello()
leg = 5
}.hello()
p.hello()
}
我们看转换成的java代码:
public final void test() {
People p = new People();
p.setEye(3);
p.hello();
p.setLeg(5);
p.hello();
p.hello();
}
由java代码也可以看出,apply函数极大的简化了给对象赋值等操作,并且会将自身返回。kotlin的这些语法糖还是很有意思的!