- 类
kotlin中普通类的声明和java中普通类的声明一致,即 class 类名 {} 声明。- 类的成员
- 构造函数与初始化块
- 函数
- 属性
- 嵌套类和内部类
- 对象声明
- 构造函数及其初始化模块
- 构造函数
- java 中类的声明后会自动创建一个无参构造方法,用于类的无参对象创建,可以创建对应的多个参数构造方法,构造方式即修饰符-类名-参数-构造方法体,多用于类中属性的初始化赋值,赋值时可以通过this进行属性赋值。
- kotlin中类提供了一个主构造函数和多个次构造函数,同样kotlin的类的声明也会创建一个无参默认构造函数。
-
主构造函数直接在类名后面声明且通过关键字constructor声明即:
主构造函数
- 主构造函数没有注解和可见修饰符的时候可以将前面的关键字取消,即直接在类名后面写构造参数即可。
- 主构造函数中的参数可以在init初始化块中直接使用也可以在类中的属性声明中直接使用
- 主构造函数中的参数可以是val(只读)也可以是var(可变参数)声明的时候需要指定其类型。
- 主构造函数中的参数声明时可以指定对应的默认值且在最后可以添加最尾部逗号。
- 主构造函数若有修饰符或者注解注释则上面提到的关键字不能取消,必须带上。
-
次构造函数:可以多个在class中以函数的形式声明:即:
次构造函数
-
如果类有一个主构造函数,每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可:(没有太明白,应该是类似于java中构造方法的重载调用?)
构造函数委托
-
请注意,初始化块中的代码实际上会成为主构造函数的一部分。对主构造函数的委托发生在访问次构造函数的第一条语句时,因此所有初始化块与属性初始化器中的代码都会在次构造函数体之前执行。
即使该类没有主构造函数,这种委托仍会隐式发生,并且仍会执行初始化块:
初始化块
- kotlin的类和java类似会自动生成一个无参主构造函数,默认为public,若不想其为public则可以主动声明一个private权限的无参构造函数且kotlin主动声明主构造函数的参数都有值的情况下系统也会自动生成一个无参主构造函数。
-
-
-
主构造函数直接在类名后面声明且通过关键字constructor声明即:
- 类的对象创建:
- 和java的对象创建类似,不同的是语法上不需要new关键字,直接对象并在()中填入参数即可。
- 初始化块
- java中存在初始化块和静态初始化块:
- 初始化块的语法是类中{}包裹即可,静态初始化块的语法是在{}前使用关键字static声明。
- 初始化块和静态初始化块的区别:静态初始化块是针对类的,初始化块是针对类的某个对象的,静态初始化块优先于初始化块执行。
- 初始化块和构造方法的执行顺序:初始化块优先于构造方法执行,且前面的初始化块比后面的先执行。可以写多个初始化块但是不建议意义不大。
- 初始化块和类中属性的执行顺序:两者执行顺序取决于代码谁在前面,若属性代码在前属性代码优先 若初始化块在前初始化块优先,所以需要校验属性的空判断,不然可能没有声明属性就执行了初始化块造成空指针异常。
- kotlin也可以写初始化块,语法是 init{}
- 初始化块和属性初始化器跟随者主构造函数执行,即在初始化块和属性初始化器中可以使用主构造函数声明的参数。
- 次构造函数的执行顺序在主构造函数的后面且在初始化块的执行顺序后面执行。
- java中存在初始化块和静态初始化块:
- 构造函数
- 属性
-
kotlin可以通过val声明一个只读属性通过var声明一个可变属性,属性的完整声明语法:
image.png
image.png
- 其初始器(initializer)、getter 和 setter 都是可选的。属性类型如果可以从初始器, 或其 getter 的返回值(如下文所示)中推断出来,也可以省略:
- 一个只读属性的语法和一个可变的属性的语法有两方面的不同: 1、只读属性的用 val 而不是 var 声明 2、只读属性不允许 setter
- 针对属性的set和get,系统会为其自动生成,val仅有getvar存在get和set,当前也可以自定义两个函数,若自定义则访问和设置的时候都会访问到自定义的函数。
- 幕后字段:即在属性的set/get函数中使用,kotlin自动生成一个字段等同于声明的属性,即这个字段叫做field,即在属性的set函数中使用field等同于当前属性。
- 幕后字段(后端域变量/备用字段/支持字段):翻译的名称不一样,其实都是一个东西,都是在类的属性声明中kotlin自动生成的一个字段,和声明的属性等同字段,仅在属性的set/get中可以访问,其他不能够访问。
- 属性的默认声明,kotlin会自动生成幕后字段,通过关键字field访问。
- 属性的set和get自定义且在自定义过程中没有访问field字段,则kotlin不会生成此字段。
- 对类中的属性的访问不依赖于此字段。
- 幕后属性:在class中如果一个属性不方便被外界直接使用可以将其声明为私有,再同时声明一个公共的属性被外界访问,类似于代理模式。
-
编译期常量:使用关键字const声明的常量被称为编译期常量,和常量区别为:一是常量可以是类型二是常量可以有自定义的getter实现。其要求必须为:
编译期常量
- 延迟初始化属性:kotlin的一个特性就是会对正常声明的属性进行判空,延迟初始化即是通过关键字告诉kotlin不需要在编译阶段进行验空操作,但是在属性使用的时候需要做判空操作,不然属性若为空报空指针异常,其将判空操作延迟到属性使用的时候,具体参考下面的文章描述。使用过程中建议属性判空。
- 委托属性:当前没弄明白,后续弄明白再补充。
-
- 伴生对象:
- 类的成员
- 抽象类
- kotlin抽象类和java类似在class前面使用abstract声明即可:
- kotlin抽象类可以继承正常的类,java中不允许只能反过来继承。
- kotlin中抽象类可以将函数抽象即没有对应的函数实现。
- 由于kotlin可以继承open的正常类,则其可以将正常带有实现体的函数再次抽象。
- kotlin抽象类和java类似在class前面使用abstract声明即可:
- 接口(函数式接口)
- java中接口的定义:接口内可以定义属性和方法,属性是公共静态且不可修改的属性,方法只能是抽象方法,没有具体的实现体。
- kotlin中接口的定义:
- 接口可以定义属性,其属性抽象或者提供了对应的get实现。
- 接口定义的函数可以抽象也可以有对应的实现体
- 类对接口的实现和对类的继承语法一致,通过关键字:实现。
- kotlin的接口支持继承,在继承接口中即可以声明新的属性,也可以实现父接口中的抽象属性。
- kotlin支持实现多接口,对于所有接口中的抽象方法都得实现才行,在实现方法中可以使用语法super<A> 调用父接口中的函数,注意<>内部可以区分父接口。
- kotlin:函数式接口(SAM接口):
- 函数式接口:在接口中可以有多个非抽象函数实现,但是仅仅有一个抽象函数实现 此接口可以被称为函数式接口。
- 语法:fun interface KRunnable { 唯一抽象函数 }
- 函数是接口的lambad简化实现:?????后续熟悉lambad后再来维护完善此处。
- 继承
- java的超类是object kotlin的超类是Any 内部函数和java一致:包含equals()、 hashCode() 与 toString()。
- java中的类都可以成为另一个类的父类,其子类继承并扩展父类的属性和方法进而扩展功能。
- kotlin不然,kotlin的类是final的不允许被继承,若要是kotlin中某个类可以被继承则其需要使用关键字open进行描述。其内部的函数也是final的,若要被重写也需要关键字open进行描述。
-
如果派生类有一个主构造函数,其基类可以(并且必须)根据其参数在该主构造函数中初始化。
image.png
-
如果派生类没有主构造函数,那么每个次构造函数必须使用super 关键字初始化其基类型,或委托给另一个做到这点的构造函数。 请注意,在这种情况下,不同的次构造函数可以调用基类型的不同的构造函数:
image.png
-
子类可以覆盖超类中的函数,覆盖需要关键字override 进行标识,且覆盖的函数在超类中需要open进行标识,若没有open标识则子类不允许声明相同的函数,子类重写后的函数是开发的,后续子类可以继续重写 而不需要再次使用open声明,倘若重写后的函数不需要再次被重写可以使用关键字final进行声明。
image.png
image.png
-
继承中属性的覆盖和函数的覆盖一致,也是依赖open和override实现,不同的是在子类中可以使用var覆盖val声明的属性还有就是子类的主构造函数中可以覆盖父类的声明的属性,即:
image.png
image.png
-
- 父类和子类的执行顺序:父类先执行即父类的构造方法先执行,然后子类在执行,子类的构造方法在执行,由于此执行顺序导致父类设计时父类的属性初始化器和初始化块尽量不要使用open声明的属性,因为此时二者的执行在父类构造函数后面但是在子类的构造函数前面,此时子类的构造函数还没有执行所以可能存在数据赋值问题。
-
子类中若调用父类的属性函数可以通过super进行调用,在类的内部类中调用其父类的属性函数通过super@外部类类名进行调用,即:
image.png
- kotlin和java一致,不支持类的多继承,实现多个接口进而多继承,但是kotlin的继承和接口实现语法一致。
- kotlin实现多个接口,其必须对接口内的抽象函数和属性完全实现。且在其内部实现的过程中可以通过super<父类类名>区别其父类的属性和函数。
-
- 类,属性,函数等的权限(可见性修饰符)
- kotlin的包声明和文件夹目录声明规则:
- Kotlin中一个kt文件中可以放多个public的类(Kotlin默认的访问权限就是public,所以可以省略)
- Kotlin中同样使用package关键字声明一个包
- Kotlin中的包声明目录名之间同样使用.来分割
- Kotlin中的包声明不需要与目录结构对应,即包声明更像是一个命名空间,和文件在硬盘上的存储没有关系,更多的是唯一的标识一个class,不过在日常的开发中还是建议包名和目录名一致。
- kotlin的导入规则:
- 默认导入:kotlin文件会默认导入kotlin的系统包及其工具包和额外的包。
- 单个class的导入及其单个class的属性和函数的导入
- class、属性、函数、顶层函数和属性、枚举常量、对象声明中声明的函数及其属性。
-
对于单个导入的可以指定一个别名。
image.png
- kotlin的可见性修饰符即java中的权限:
- java中的权限默认+private+public+protected四种权限,未声明表示默认权限,其默认权限在整个包内可以使用。
- kotlin的权限也是上面四种权限只是包内权限不是默认的需要通过关键字internal进行声明且kotlin的不声明权限默认权限是public。
- 顶层声明:java中属性和函数的声明必须声明在class中,kotlin可以将属性和函数不声明在class中 在包的文件中直接声明属性和函数,此时编译成java文件可以发现此时声明的属性和函数都属于当前的kt文件类。
- 顶层声明的权限仅有public,private,internal,默认是public。protected不适用于顶层声明。
- 类及其类属性和函数:
- 权限还是原有四种
- kotlin的外部类不能直接访问内部类的private属性和函数
- 子类覆盖父类的属性和函数若没有修改其修饰符则其还是保留其原有的修饰符及其权限。
参考文章:
kotlin:伴生对象
java初始化块
kotlin延迟初始化属性
kotlin:幕后字段(后端域变量)
- kotlin的包声明和文件夹目录声明规则:
网友评论