kotlin小记(1)

发布于:2025-08-03 ⋅ 阅读:(14) ⋅ 点赞:(0)

1.次构造函数

可以理解为是在对主构造函数进行”重载“,但是必须要直接或间接代理上主构造函数,使得主构造函数的值传入次构造中;

open class Person(var a1 : Int) {  
  
    constructor(a2 : String) : this(0) {  
    }  
    
    constructor(a1 : Int, a2 : Int) : this(a1){  
  
    }  
}

2.open关键字

只有被open修饰的类,才可以被继承。被open修饰的方法,才能被重写.被open修饰的属性,才能够被重写(属性被open修饰后,必须初始化,不能被lateinit修饰,也不能只在init中被初始化)

open class Person(var a1 : Int) { 
    open fun test(){}
    open var time : Int
}

3.类的修饰符

- classModifier: 类属性修饰符,标示类本身特性。
    
    final       // 类不可继承,默认属性
    open        // 类可继承,类默认是final的
    abstract    // 抽象类  
    enum        // 枚举类
    annotation  // 注解类

- accessModifier: 访问权限修饰符
    
    private    // 仅在同一个文件中可见
    protected  // 同一个文件中或子类可见
    public     // 所有调用的地方都可见
    internal   // 同一个模块中可见

4.子类继承

子类有主构造函数, 则基类必须在主构造函数中立即初始化。
子类没有主构造函数,则基类可以在类头或次构造函数中初始化

open class Person(var a1 : Int) {  
  
}
//子类有主构造函数
class child(a1 :Int) : Person(100){  
  
}  

//子类没有主构造函数
class man : Person(100) {  
  
}  
  
class felman : Person{  
  
    constructor(a1 : Int) : super(101){  
  
    }
}

5.属性重写

你可以用一个var属性重写一个val属性,但是反过来不行。因为val属性本身定义了getter方法,重写为var属性会在衍生类中额外声明一个setter方法(子类重写父类属性,也就相当于必须重写该属性的 getter 和 setter 方法,而子类中的 val 不能有 setter 方法,所以无法“覆盖”父类中 var 的 setter 方法,相当于缩小了父类中相应属性的使用范围,是不允许的,就像我们不能把父类中一个 public 方法重写成 private 方法一样。)

6.拓展函数

对类的属性和方法进行拓展,不需要继承和装饰器模式
一种静态行为,对被扩展的类代码本身不造成任何影响

class Test {  
    var num = 1  
}  
  
fun Test.goo(){  
    println("${num}")  
}

fun <T> MutableList<T>.len() : Int {  
    return this.size  
}


拓展函数是静态解析的

open class C

class D: C()

fun C.foo() = "c"   // 扩展函数 foo

fun D.foo() = "d"   // 扩展函数 foo

fun printFoo(c: C) {
    println(c.foo())  // 输出 c
}


若扩展函数和成员函数一致,则使用该函数时,会优先使用成员函数。

7.泛型

泛型:将类型作为一个参数使用,可以用在类,接口,方法上
使用 out 使得一个类型参数协变,协变类型参数只能用作输出,可以作为返回值类型但是无法作为入参的类型:
in 使得一个类型参数逆变,逆变类型参数只能用作输入,可以作为入参的类型但是无法作为返回值的类型:

class test2<out T>(val time : T){  
    fun getTime() : T{  
        return time  
    }  
}  
  
class test3<in T>(){  
    fun getTime(time : T){  
    }  
}

8.数据类在结构声明中使用

data class User(  
    var name : String,  
    var age : Int  
)  
  
fun main() {  
    val jane = User("jane", 35)  
  
    val(name, age) = jane  
    println("$name, $age is ")  
}

9.密封类

和枚举的对比

enum class Color(var lab : Int, var namex : String){  
    RED(0xFF0000, "red"),   //每个实例携带的信息相同
    GREEN(0x00FF00, "green"),  
    BLUE(0x0000FF, "blue")  
}
  
sealed class Users{  
    object Unknown : Users()  
    data class Man(val age: Int) : Users()  //实例可携带不同的信息
    data class Felman(val name: String) : Users()  
}

每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。
密封类通常和when搭配使用

sealed class Users{  
    object Unknown : Users()  
    data class Man(val age: Int) : Users()  
    data class Felman(val name: String) : Users()  
}  
  
fun getSex(users: Users) : Int = when(users){  
    Users.Unknown -> 0  //没有额外参数时,不用is
    is Users.Man -> 1  
    is Users.Felman -> 2  //因为涵盖了所有实例分支,所以不用else
}

10,枚举类实现单例,每个枚举常量只存在一个实例
枚举类已经隐式地继承了Enum类,所以枚举类不能继承其他类,但是可以实现接口

  
enum class Singleton{  
    INSTANCE;  
}

// 编译器生成的Java代码(简化版)

public final class Singleton extends Enum<Singleton> {

    public static final Singleton INSTANCE = new Singleton();
    
    private Singleton() {
    // 私有构造函数
    }

    // 其他枚举相关方法...
}