Kotlin 入门到进阶(12) -- Class、Interface

  • create class
class Person3 {

    //可变属性
    var name: String? = null
    //不可变属性
    val age: Int = 0

    //如果使用private修饰,则不会有getter和setter方法
    //外面就无法访问该属性了
    private var gender: Int = -1
}
  • primary constructor
class Person (val name: String) //只会生成name的getter方法
  • secondary constructor
//构造方法和class声明在同一行时,该构造方法被称之为 Primary Constructor
//如果构造方法在类的内部声明,该构造方法被称之为 Secondary Constructor
//Primary Constructor和 Secondary Constructor区别:
//Primary Constructor 构造方法的参数如果有val/var修饰,那么该类会生成和该参数一样的属性,以及与之对应setter和getter(如果是var修饰会有getter和setter,val修饰只有getter)
//Secondary Constructor 构造方法的参数不能用val/var属性
open class Person5(var bool:Boolean){
    var name: String? = null
    var id: Int = 0
    constructor(name: String) : this(false) {
        this.name = name
    }
    constructor(id: Int) : this("AAA") {
        this.id = id
    }

}
  • companion object
    伴生对象,可在内部生成静态常量、实现接口、内部对象的函数等
    companion object {
        //公共常量
        const val FEMALE: Int = 0
        const val MALE: Int = 1

        //私有常量
        val GENDER: Int = FEMALE

        //静态变量
        var username: String = "chiclaim"

        //静态方法
        fun run() {
            println("run...")
        }
    }
interface IAnimal {
    fun eat()
}

class ObjectKeywordTest4 {

    companion object : IAnimal {
        override fun eat() {
            println("eating apple")
        }
    }
}
    companion object Cache {
        fun save2DB() {
            println("save data to database...")
        }

        fun save2Memory() {
            println("save data to memory...")
        }
    }
  • object class
// 单例
object Singleton
  • init block
    类在对象初始化时,调用的函数
open class Person7 {
    var name: String? = null
    var id: Int = 0


    constructor(name: String) {
        this.name = name
    }

    constructor(id: Int){
        this.id = id
    }

    //构造对象的时候,init代码块只会被执行一次
    init {
        System.out.println("init----------")
    }

}

执行完 init 函数之后,再执行构造函数里面的逻辑,反编译后可以看到 init 之后才执行 name 的赋值

截屏2025-01-31 17.27.29.png
  • inner class
    内部类关键字
class OuterClass {

    //和Java不同,在Kotlin中内部类默认是静态的,不持有外部类的引用
    class InnerStaticClass{

    }

    //如果要声明非静态的内部类,需要加上inner关键字
    inner class InnerClass{

    }
}

密封类与枚举的比较
密封类和枚举都表示有限的值集合,但它们有不同的用途。
枚举
• 适用于固定常量集合(如一周的天数)。
• 简单且易于使用。
• 可以包括属性和方法。
密封类
• 更灵活。
• 可以保存不同类型的数据。
• 允许每种类型有不同的实现。

enum class Color {
    RED, GREEN, BLUE
}
 
sealed class Shape {
    object Circle : Shape()
    object Square : Shape()
    data class Rectangle(val height: Int, val width: Int) : Shape()
}

反编译后和原始输入的对比

在这个生成的字节码中:
• NetworkResult 是一个抽象类。
• Success 和 Error 是静态嵌套类,具有各自的数据字段(data 和 exception)。
• Loading 是一个表示单例对象的静态嵌套类,具有单个实例(INSTANCE)。

sealed class NetworkResult {
    data class Success(val data: String) : NetworkResult()
    data class Error(val exception: Throwable) : NetworkResult()
    object Loading : NetworkResult()
}
public abstract class NetworkResult {
    public static final class Success extends NetworkResult {
        private final String data;
 
        public Success(String data) {
            this.data = data;
        }
 
        public String getData() {
            return data;
        }
    }
 
    public static final class Error extends NetworkResult {
        private final Throwable exception;
 
        public Error(Throwable exception) {
            this.exception = exception;
        }
 
        public Throwable getException() {
            return exception;
        }
    }
 
    public static final class Loading extends NetworkResult {
        public static final Loading INSTANCE = new Loading();
 
        private Loading() {}
    }
}
  • data class
    简单理解为常规实体类,无需显式编写 get/set 方法,会自动生成 get/set 方法
data class User(val nickname: String)
  • interface

Kotlin 中的接口,可以定义 变量 和 函数(内部可以有逻辑实现),java 不允许在接口中定义 变量/函数

interface InterfaceTest {

    var count: Int

    fun plus(num: Int) {
        count += num
    }

}

class Impl : InterfaceTest {
    override var count: Int = 0

    override fun plus(num: Int) {
        super.plus(num)
        println("invoke plus")
    }
}

/*

Java8之前的接口是不允许有变量和方法的,那么Kotlin是如何实现的呢?

Kotlin 接口中的变量底层只是setter和setter方法
Kotlin 接口中的方法并不是真的有方法体,底层也只有声明。只是在接口的内部新建一个静态内部类
       内部类的里静态方法名就是我们在接口里声明有方法体的方法,静态方法有个额外的接口类型的参数,但是对我们开发者是透明的
       接口里有方法体的方法在实现类里是不强制我们实现的,不是不需要,而是Kotlin已经替我们做了

    public interface InterfaceTest {
       int getCount();
       void setCount(int var1);
       void plus(int var1);
       void test();

       public static final class DefaultImpls {
          public static void plus(InterfaceTest $this, int num) {
             $this.setCount($this.getCount() + num);
          }

          public static void test(InterfaceTest $this) {
             String var1 = "";
             System.out.print(var1);
          }
       }
    }

    public final class Impl implements InterfaceTest {
       private int count;

       public int getCount() {
          return this.count;
       }

       public void setCount(int var1) {
          this.count = var1;
       }

       public void plus(int num) {
          InterfaceTest.DefaultImpls.plus(this, num);
       }

       public void test() {
          InterfaceTest.DefaultImpls.test(this);
       }
    }


 */
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容