• kotlin类


    一、定义

    1、kotlin中使用关键字class 声明类,如果一个类没有类体,也可以省略花括号, 默认为public 类型的:

    1. // 这段代码定义了一个公开的、不可被继承的Test类
    2. class Test{
    3. }
    4. // 没有类体,可以省略花括号
    5. class Test

    底层代码:class Test{} / class Test 底层编译成java代码 如下:

    1. // final: 这个关键字说明Test类是一个最终类,意味着它不能被继承。
    2. // 也就是说,不允许有其他类继承自Test类以扩展其功能。
    3. public final class Test {
    4. }

    2、类中定义的变量必须初始化

    1. class Foo{
    2. val x:Int = 1
    3. }

    二、构造函数

    1、主构造函数:

    (1)在kotlin中,一个类有一个主构造函数,并且可以有一个或者多个次构造函数。
    注:所有次构造函数必须调用主构造函数。

    1. // 下边定义类的主构造函数,且添加了2个Int类型的参数
    2. class Test constructor(a: Int, b: Int) {
    3. }
    4. // 也可以省略constructor关键字,如果主构造函数没有任何注解或可见性修饰符:
    5. class Test (a: Int, b: Int) {
    6. }

    (2)主构造函数的参数也可以作为类的属性存在,下边ab 同时作为构造函数的参数和类的属性存在

    1. // a和 b 都是类的属性
    2. class Test constructor(val a: Int, var b: Int) {
    3. }
    4. // 也可以给参数使用默认值:
    5. class Test constructor(val a: Int = 1, var b: Int = 2) {
    6. }
    7. // 或者在类里边定义属性
    8. class Test01 (a: Int, b: Int) {
    9. // 在类定义类属性,此时a和b作为参数传进来
    10. var c: Int = a // 定义类属性c
    11. var d: Int = b // 定义类属性d
    12. init {
    13. println("$c+$d=${c+d}")
    14. }
    15. }
    16. fun main() {
    17. Test01(1, 2)
    18. }

    作为参数:
    构造函数定义中,ab 接收从外界传入的具体值,允许在创建 Test01 类的实例时初始化这些值。

    作为属性
    val a: Int 表明 a 是一个只读属性(final变量),一旦在构造函数中初始化后,其值就不能再改变。
    var b: Int 表明 b 是一个可变属性(变量),在类的实例创建后,其值仍然可以被修改。

    (3)类变量初始化时机

    1、参数传递,初始化类中变量。

    2、使用定义的默认值,初始化类变量。

    3、如果不想第一时间初始化变量,可以使用 lateinit 懒加载:

    1. class Test () {
    2. lateinit var a: String
    3. lateinit var b: String
    4. }

    注意事项:

    为什么Int类型不能使用lateinit 懒加载?

    原因如下:
    对于基本数据类型(如 IntDoubleBoolean 等),它们不能为 null,并且在声明时必须赋予一个初始值。由于基本类型不是引用类型,它们不存在“未初始化”的状态——它们要么有一个具体的值,要么在局部作用域内如果没有初始化就会导致编译错误。因此,lateinit 机制不适用于基本数据类型,因为基本类型总是有默认值(如 Int 的默认值是 0),且不能为 null

    (4)在类里边定义变量,kotlin默认会为每个属性添加getter和setter,当然你也可以显示的定义getter和setter

    1. class Test (b:Int) {
    2. var a: Int = b
    3. // 为a变量定义getter,打印a变量时,输出2,getter优先级是最高的
    4. get() {
    5. return 2
    6. }
    7. set(value) {
    8. field = value
    9. }
    10. init {
    11. println(a) // 2
    12. }
    13. }
    14. fun main() {
    15. Test(1)
    16. }

    类中属性的引用,跟方法引用一样:

    1. // 方法定义
    2. fun main() {
    3. // 引用Foo类中的x属性
    4. val r = Foo::x
    5. // 方式一:调用Foo类中的x属性,获取其值
    6. val r1 = r.get(Foo("hello"))
    7. println("r1 -> $r1") // r1 -> hello
    8. // 方式二:通过实例化的对象foo来引用Foo类中的x属性
    9. val foo = Foo("world")
    10. val r2 = foo::x
    11. println("r2 -> ${r2.get()}") // r2 -> world
    12. }
    13. class Foo(x:String) {
    14. val x:String = x
    15. }

    2、次构造函数:

    (1)创建
    1. // 记住一点:所有的次构造函数必须要调用主构造函数。
    2. class Test (var name:String) {
    3. // 次构造函数的创建如下,
    4. // (1)在类里边添加constructor关键字
    5. // (2)通过this()来调用主构造函数 Test()
    6. // 且this()参数必须和主构造函数的参数一致
    7. constructor(name:String,age:Int): this(name){}
    8. }

    三、类实例化

    1、在kotlin中实例化类后,会创建一个新的对象,并且返回对象的引用,在构造函数执行完毕后,会返回一个指向新创建对象的引用,这个引用可以被存储在一个变量中,以便后续使用。

    1. class Test (var name:String)
    2. fun main() {
    3. val user:Test =Test("小王")
    4. // 通过user变量可以访问类中的属性、函数
    5. println(user.name) // 小王
    6. }

    2、类方法定义及调用

    1. class Test(name: String) {
    2. // 定义info方法,参数为String类型
    3. fun info(name: String) {
    4. // 就近原则:所以输出 2
    5. println("名字为:${name}") // 2
    6. }
    7. }
    8. fun main() {
    9. val test = Test("1")
    10. test.info("2")
    11. }

    在方法中,如果想调用主构造函数参数,需要使用 this. 的方式,且主构造函数参数必须是属性。

    1. class Test(var name: String) {
    2. fun info(name: String) {
    3. // this 就是Test 实例化的对象
    4. println("名字为:${this.name}") // 1
    5. }
    6. }
    7. fun main() {
    8. val test = Test("1")
    9. test.info("2")
    10. }

    四、接口

    1、定义

    1. // Foo类 实现 FooInterface接口
    2. class Foo(val x: String):FooInterface{
    3. // 重写接口中foo方法
    4. override fun foo() {
    5. TODO("Not yet implemented")
    6. }
    7. }
    8. // 定义接口
    9. interface FooInterface {
    10. // 定义接口中的方法
    11. fun foo()
    12. }

    2、实现接口

    接口的实现,需要在实现类后边加上 ,后边写上接口类名即可

    1. // Foo类实现 FooInterface接口
    2. class Foo(val x: String):FooInterface{
    3. }

    注意事项:

    (1)接口的定义,不需要添加关键字 class
    (2)实现类继承某个接口,后边添加 : 然后填写接口名即可 class T( ): AInterface{ }
    (3)重写接口中的方法,在实现类中 需要添加 关键字 override

    五、抽象类

    1、定义

    1. // 定义抽象类
    2. abstract class FooAbstract {
    3. // 定义抽象类中的方法
    4. abstract fun foo()
    5. }

    2、抽象类中,如果没定义abstract 关键字, 那么该方法默认是不可被重写的;如果需要重写,必须加上关键字 open :

    1. // 定义抽象类
    2. abstract class FooAbstract {
    3. // 定义抽象方法,可以被重写
    4. abstract fun gar()
    5. // 不可被重写的方法
    6. fun foo(){}
    7. // 可被重写的方法
    8. open fun bar(){}
    9. }

    3、类实现抽象类,重写里边的方法:

    1. // Foo类 实现 FooAbstract抽象类
    2. class Foo(val x: String):FooAbstract(){
    3. // 重写接口中foo方法
    4. override fun bar() {
    5. println("Foo:$x")
    6. }
    7. override fun gar() {
    8. println("Foo:$x")
    9. }
    10. }
    11. // 定义抽象类
    12. abstract class FooAbstract {
    13. // 定义抽象方法,可以被重写
    14. abstract fun gar()
    15. // 不可被重写的方法
    16. fun foo(){}
    17. // 可被重写的方法
    18. open fun bar(){}
    19. }

    注意事项:

    (1)定义抽象类,前边加上 abstract  关键字。
    (2)抽象类中的方法(注意不是抽象方法),默认是不可被重写的,必须显示的加上关键字 open,才可以被重写。
    (3)抽象类中的所有方法,有关键字 abstract  和open的方法,在实现类里边,必须全部被重写,否则不会被编译通过。
    (4)继承抽象类写法  class T( ): Aabstract( ) { } ,抽象类后边必须添加括号。
    (5)重写抽象类中的方法,跟接口实现一样,在实现类中 也需要添加 关键字 override

    六、同时继承接口及抽象类

    1. // Foo类 实现 FooAbstract抽象类、FooInterface接口
    2. class Foo(val x: String):FooAbstract(), FooInterface{
    3. // 重写了抽象类中 foo方法
    4. override fun foo() {
    5. TODO("Not yet implemented")
    6. }
    7. // 重写了接口中 bar方法
    8. override fun bar() {
    9. TODO("Not yet implemented")
    10. }
    11. }
    12. // 定义抽象类
    13. abstract class FooAbstract {
    14. abstract fun foo()
    15. }
    16. // 定义接口
    17. interface FooInterface{
    18. fun bar()
    19. }

    六、普通类的继承

    1、继承普通类,普通类前边必须添加 open 关键字,才能被别的类继承:

    1. // Foo类 实现 FooAbstract抽象类、FooInterface接口
    2. open class Foo(val x: String):FooAbstract(), FooInterface{
    3. override fun foo() {
    4. TODO("Not yet implemented")
    5. }
    6. override fun bar() {
    7. TODO("Not yet implemented")
    8. }
    9. }
    10. // Foo2 继承 Foo 类,Foo类前边必须添加关键字 open
    11. class Foo2(val y: String):Foo(y){
    12. }
    13. // 定义抽象类
    14. abstract class FooAbstract {
    15. abstract fun foo()
    16. }
    17. // 定义接口
    18. interface FooInterface{
    19. fun bar()
    20. }
    21. fun main(){
    22. Foo2("hello")
    23. }

    2、被继承类中的方法,如果不想被别的类复写某个方法,可以在方法卡那边加上关键字 final

    1. open class Foo(a:String): FooInterface, FooAbstractClass(){
    2. override fun foo() {
    3. TODO("Not yet implemented")
    4. }
    5. // bar 方法不可被别的类重写
    6. final override fun bar() {
    7. TODO("Not yet implemented")
    8. }
    9. }
    10. class Foo2(val a: String):Foo(a){
    11. override fun foo() {
    12. }
    13. // 编译不会通过,因为Foo类中的bar方法,前边有关键字 final
    14. override fun bar() {
    15. }
    16. }
    17. abstract class FooAbstractClass {
    18. abstract fun foo()
    19. }
    20. interface FooInterface {
    21. fun bar()
    22. }

  • 相关阅读:
    免费 DIY 之旅问题
    基于JAVA课程网站设计计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    Nginx 同一端口下部署多个 Vue3 项目
    夜天之书 #90 再谈 Rust 项目社群治理
    面试系列MySql:谈谈B树、B+树的原理及区别
    Python实现的基于keras做CNN
    NLP(3)--利用nn反向计算参数
    提振信心!1-7月新车智能化「持续增长」,同比增速超70%
    HTML网页大作业代码【免费代码已上传】
    `dump` 和 `load` 以及 `dumps` 和 `loads`的用法
  • 原文地址:https://blog.csdn.net/qq_42778001/article/details/139668308