Day08对象和伴生对象

1、对象声明
2、伴生对象
3、@JvmField 和 @JvmStatic 的使用
4、const 关键字
5、object,companion和const区别
6、伴生对象的扩展函数和扩展属性

一、对象声明

Kotlin 使用 object 关键字来声明一个静态对象。
在kotlin中,类是没有显式的static方法和static成员变量的,都是通过伴生对象的形式间接提供的。

fun main() {
    Student.eat()
}

object Student {
    fun eat() {
        print("吃吃吃")
    }
}

Student 相当于java的

public final class Student2 {
    public static void say() {
        System.out.println("Hello");
    }
}

二、伴生对象

Kotlin 中,在类中定义的对象(object)声明,可使用 companion 修饰,这样此对象(object)就是伴生对象了

class Teacher {
    companion object test {
        var name: String = "A老师"
        fun say() {
            print("好好学习")
        }
    }
}

在上面的 Teacher 类中, test 是一个伴生对象,其中有一个 name 属性 和 say 方法.
在kotlin中调用:

fun main() {
   Teacher.say()
    print(Teacher.name)
}

通过上面的 Teacher.say()Teacher.name 代码不难看出来,类似于 Java 中使用类访问静态成员的语法。因为 Kotlin 取消了 static 关键字,所以 Kotlin 引入伴生对象来弥补没有静态成员的不足。可见,伴生对象的主要作用就是为其所在的外部类模拟静态成员。其中可以省略test对象名称,实际上是在这个类内部创建了一个名为 Companion 的静态单例内部类,伴生对象中定义的属性会直接编译为外部类的静态字段,而函数会被编译为伴生对象的方法。
注意:1、一个类里面只能声明一个内部关联对象,即关键字 companion 只能使用一次。

在 java 中调用:

public static void main(String[] args) {
      Teacher.Companion.say();
      System.out.println( Teacher.Companion.getName());

  }

如果伴生对象有名称:

类名.伴生对象名.方法名()
类名.半生对象名.属性的setter,getter方法

Teacher.test.say();
 System.out.println( Teacher.test.getName());

如果伴生对象没有名称,则使用 Companion 关键字:

类名.Companion.方法名()
类名.Companion.属性的setter,getter方法

 Teacher.Companion.say();
 System.out.println( Teacher.Companion.getName());

三、 @JvmField 和 @JvmStatic 的使用

我们知道了可以在 Java 代码中调用 Kotlin 中伴生对象的成员,类似于 Java 类中的静态成员。但是看上去和 Java 中的还是略有区别,因为类名和方法名/属性setter,getter方法名之间多了个伴生对象的名称或者 Companion 关键字。为了和 Java 中的调用看上去一样,Kotlin 为我们提供了 @JvmField 和 @JvmStatic 两个注解。
@JvmField 使用在属性上,@JvmStatic 使用在方法上。

class Teacher {
    companion object test {
        @JvmField
        var name: String = "A老师"

        @JvmStatic
        fun say() {
            print("好好学习")
        }
    }
}

java调用

  public static void main(String[] args) {
        Teacher.say();
        System.out.println( Teacher.name);

    }

这个注解,只对java的调用方式有影响,对kotlin的调用方法,没影响.

四、const 关键字

在伴生对象中,我们可能需要声明一个常量,目的是等同于 Java 中的静态常量。有两种方式,一种是上面所提到的使用 @JvmField 注解,另一种则是使用 const 关键字修饰。这两种声明方式都等同于 Java 中 static final 所修饰的变量。

class Teacher {
    companion object test {

        const val age: Int = 20

        @JvmField
        var name: String = "A老师"

        @JvmStatic
        fun say() {
            print("好好学习")
        }
    }
}

kotlin 调用:

    Teacher.say()
    print(Teacher.name)
    print(Teacher.age)

java调用:

  public static void main(String[] args) {
        Teacher.say();
        System.out.println(Teacher.name);
        System.out.println(Teacher.age);
        //如果不写 Teacher 类的 伴生对象 test 中的 const 关键字
        System.out.println(Teacher.test.getAge());
    }

const 关键字使用的影响只是在 Java 中调用方式不同,在 Kotlin 中并无影响。

五、object,companion和const区别

object:用对象表达式和对象声明实现Java匿名内部类这种情况,即匿名类的实现对象为object。
companion object{} :伴生对象,虽然调用的时候类似static,但它依然是对象的实例成员,并且可以实现接口
const :编译时常量。1.String或基本类型进行初始化;2.没有自定义getter;3对象成员或顶级(Top-level)。从实际上看,它更符合static final的常量

六、伴生对象的扩展函数和扩展属性

fun Teacher.test.sleep() {
    print("我说扩展方法")
}
var Teacher.test.sex
    get() = 3
    set(value) {

    }
val Teacher.test.height
    get() = 180
class Teacher {
    companion object test {
        val age: Int = 20
        @JvmField
        var name: String = "A老师"
        @JvmStatic
        fun say() {
            print("好好学习")
        }
    }
}

1、如果伴生对象有名称的话,使用类名.伴生对象名.方法名()来扩展,否则使用 类名.Companion.方法名()来扩展
2、扩展属性不能有初始值,没有 field 来存储属性值;
3、扩展属性因为没字段来存储值,所以为计算属性;
4、扩展 var 属性必须提供 setter 和 getter 方法,扩展 val 属性必须提供 getter 属性。
调用:

fun main() {
    print(Teacher.sleep())
    print(Teacher.sex)
    print(Teacher.height)

}

小结:
1、每个类可以最多有一个用companion object 修饰的伴生对象;
2、伴生对象的成员类似于 Java 的静态成员;
3、使用 const 关键字修饰常量,类似于 Java 中的 static final修饰。
4、可以使用 @JvmField 和 @JvmStatic 类似于 Java 中调用静态属性和静态方法.

你可能感兴趣的:(Day08对象和伴生对象)