六、Kotlin 类型进阶


1. 类的构造器 & init 代码块

1.1 主构造器 & 副构造器在使用时的注意事项 & 注解 @JvmOverloads

  1. 推荐在类定义时为类提供一个主构造器;

  2. 在为类提供了主构造器的情况下,当再定义其他的副构造器时,要求副构造器必须调用到主构造器,否则报语法错误;

  3. 在继承时,如果父类中定义了主构造器或者副构造器,那么子类在继承父类时要在子类的构造器后面指明所调用的父类构器;

  4. 可以在定义构造器时为形参提供默认参数值;

  5. 如果要在 Java 中调用 Kotlin 类的带默认参数值的构造器,需要使用注解 @JvmOverloads 修饰 Kotlin 类的带默认参数值构造器。此时就相当于 Java 把带默认参数值的构造器分解成多个重载的构造器。

1.2 init 代码块

  1. init{...} 代码块相当于 Java 类中的非静态代码块 {...}

  2. 二者都会在实例化对象的过程中执行,区别是 init{...} 代码块中可以访问到主构造器的形参。

  3. 先执行 init{...} 代码块,再执行副构造器的函数体。

  4. Kotlin 类的成员属性必须进行初始化。可以在定义时就初始化;也可以放到 init{...} 代码块中初始化。

  5. init{...} 代码块和 Java 类中的非静态代码块 {...} 一样,都可以定义多个。

1.3 示例 1:init 代码块 & 主/副构造器的使用

在这里插入图片描述

1.4 示例 2:在声明继承关系的同时指定所调用的父类构造器

在这里插入图片描述

1.5 示例 3:带默认参数的构造器 & 注解 @JvmOverloads 的使用场景

在这里插入图片描述

2. 使用与类同名的工厂函数创建类对象

Kotlin 中可以定义一个全局的与某个类同名的函数作为 工厂函数 来实例化这个类。从外观上看,就好像是重载了类的构造器一样

这样做的好处是:对于无法被继承的类,可以通过定义一个这样的同名的全局函数来实例化这个类,从而能够加上一些我们自己的业务代码。

示例:

在这里插入图片描述

3. 访问权限修饰符

3.1 JavaKotlin 的访问权限修饰符对比

Java Kotlin
public 公开 公开,是 Kotlin 中的默认权限
internal 模块内可见
default 包内可见,是 Java 中的默认权限
protected 包内及子类可见 子类可见
private 仅类内可见 文件内及类内可见

3.2 Kotlin 中的访问权限修饰符的作用对象

顶级声明 成员
public
internal
protected × ×
private

3.3 Kotlin 中模块的概念

IntelliJ IDEA 工程中的一个 Module 可以看成是一个 Kotlin 模块。

也就是说:一个 jar 包;一个 aar 库,都可以看成是一个 Kotlin 模块。

3.4 Kotlin 中修饰符 internal & Java 中修饰符 default

3.4.1 Java 中修饰符 default 的使用场景 & 缺陷

在封装 SDK 或对外提供公共组件时,对于 SDK 或公共组件中的核心类,若我们不想让使用者访问到,通常会使用 default 修饰,即包内可见。

但是,如果使用者一定要访问这些核心类的话,也可以创建一个与核心类同包名的包路径,将预访问这些核心类的外部类定义在同包名的包路径下即可。

也就是说,Java 中的 default 权限修饰符是存在缺陷的:

  1. 我们在封装 SDK 或封装公共组件时,无法通过 default 修饰符将核心类给彻底的对外隐藏起来。

  2. 并且,对于 default 修饰的多个核心类,如果它们之间要相互访问,那么也必须放到同一个包路径下,即包名要相同。这就意味着即使这些核心类可分为不同的功能模块、不同的抽象层次,我们也无法按照功能或抽象层次不同将它们分别放到不同的包路径下。从而导致了同一个包路径下聚集了大量的功能不同、抽象层次不同的类文件,使工程结构变得臃肿、不明确、难以维护。

3.4.2 Kotlin 中使用修饰符 internal 解决 Java 中修饰符 default 的缺陷

Kotlin 中使用 internal 修饰符可以解决 Java 中的 default 修饰符的缺陷:

  1. internal 修饰的核心类或成员只是在模块内可见。这意味着我们在一个模块中封装的 SDK 或公共组件,在提供给其他模块使用时,在其他模块中是无法访问到 SDK 或公共组件中被 internal 修饰的核心类或成员的。

  2. 并且,在模块中被 internal 修饰符的核心类并没有限制都要放在同一个包路径中才能相互访问(只要它们在同一个模块中就可以相互访问)。所以,对于可分为不同功能模块、不同抽象层次的各个核心类,可以放在同一个模块下的不同包路径中。保证了工程结构清晰明确。

3.4.3 修饰符 internalJava 中无效 & 注解 @JvmName 的作用

Kotlin 中的 internal 修饰符对 Java 是无效的。也就是说,在其他模块的 Java 代码中是可以访问到 SDK 或公共组件模块中被 internal 修饰的核心类或成员的。

需要指出的是:在其他模块的 Java 中访问 Kotlin 中被 internal 修饰的成员方法时,默认会为该成员方法的方法名添加额外的后缀 “$moduleName_buildType”。

如果不想使用这种添加了后缀的默认方法名,我们可以使用注解 @JvmName 声明在 Java 中调用时的方法名称。

特别地:如果我们不想让其他模块中的 Java 代码能够访问到被 internal 修饰的 Kotlin 中的成员方法,那么可以使用注解 @JvmName 为这个成员方法声明一个 不合法的方法名称(如声明一个非字母或下划线开头的方法名称),于是 Java 中在调用这个不合法的方法名时就会报语法错误。

示例:

在这里插入图片描述

3.5 为构造器添加访问权限修饰符

当为 Kotlin 类的主构造器添加访问权限修饰符时,不能省略主构造器中的关键字 constructor

当为 Kotlin 类的副构造器添加访问权限修饰时,直接在构造器定义的最前面加修饰符即可。

在这里插入图片描述

3.6 为 Kotlin 类的属性添加访问权限修饰符

可以在主构造器中定义成员属性时直接为该属性声明访问权限修饰符。

对于属性的 setter/getter 方法:

  1. getter 方法的访问权限修饰符必须同属性的访问权限修饰符一致;
  2. setter 方法的访问权限修饰符的权限不得超过属性的访问权限修饰符。

在这里插入图片描述

3.7 什么是顶级声明 & 为顶级声明添加访问权限修饰符

顶级声明是指:文件中定义的全局变量、全局函数、类。

顶级声明不能被 protected 修饰。

顶级声明被 private 修饰时,表示仅当前文件内可见。

4. 属性的延迟初始化

4.1 Kotlin 中属性必须赋初值 & 特殊情况下的延迟初始化

一般情况下,Kotlin 要求类属性必须赋以初始化值,具体分为两种情形:

  1. 在定义属性时赋以初始化值;
  2. init 代码块中赋以初始化值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值