Kotlin教程笔记(2)- 类与构造器

简介: Kotlin教程笔记(2)- 类与构造器

本系列学习教程笔记属于详细讲解Kotlin语法的教程,需要快速学习Kotlin语法的小伙伴可以查看“简洁” 系列的教程

快速入门请阅读如下简洁教程:
Kotlin学习教程(一)
Kotlin学习教程(二)
Kotlin学习教程(三)
Kotlin学习教程(四)
Kotlin学习教程(五)
Kotlin学习教程(六)
Kotlin学习教程(七)
Kotlin学习教程(八)
Kotlin学习教程(九)
Kotlin学习教程(十)

imgKotlin - 类与构造器

#类是什么?

类是一个抽象的概念,是具有某些特征的事物的概括,不特定指代任何一个具体的事物。写法:

class <类名> {
    <成员>
}

Number(Int、Float、Byte)、字符串(String)也是类

class Girl constructor(var nature: String,var appearance: String,var sound: String){
    // 构造方法的方法体
    init {
        println("女孩的性格:$nature,长相:$appearance,声音:$sound")
    }
}
  • constructor 是构造器关键字,如果只有一个构造器,则该关键字可以省略。
  • init 是构造方法的方法体,当用该类创建出一个对象时就会执行。
fun main(args: Array<String>) {
    val girl: Girl = Girl("温柔", "甜美", "动人") // 女孩的性格:温柔,长相:甜美,声音:动人
}

#类构造器

构造器分为两种,分别是:

  • 主构造器:紧接在类名后面的构造器,参数可以使用 var 声明,init 是主构造器的方法体。
  • 次构造器:在类代码块中声明的构造器,参数不可以使用 var 声明,与 init 无直接关系。
class Girl constructor(var nature: String, var appearance: String, var sound: String) {

    // 主构造器的方法体
    init {
        println("女孩的性格:$nature,长相:$appearance,声音:$sound")
    }

    // 次级构造器,无法使用 var 声明变量
    constructor(nature: String, appearance: String) : this(nature, appearance, sound = "未知") {
        println("次级构造器")
    }
}

fun main(args: Array<String>) {
    val girl: Girl = Girl("温柔", "甜美")
    // 输出2句:
    // 女孩的性格:温柔,长相:甜美,声音:未知
    // 次级构造器被调用
}

上面说到,次级构造器与 init 无直接关系,但次级构造器会通过 :this(...) 调用主构造器,从而触发 init 方法体执行。另外,通过输出结果,可以确定 次级构造器方法体 会比 init 方法体晚执行。

个人建议:先写 init,再写次级构造器,看起来会比较舒服。

#构造器省略 constructor 关键字

当没有次级构造器,只有一个主构造器时,可以省略 constructor 关键字:

class Girl(var nature: String, var appearance: String, var sound: String) {
    ...
}

#主构造器中的 var 参数

上面说到,主构造器的参数才能使用 var 声明,而次构造器则不行,那么主构造器中有无使用 var 声明的参数,会有何不同?

// 注意:只有nature使用了var声明
class Girl constructor(var nature: String, appearance: String, sound: String) {

    init {
        println("女孩的性格:$nature,长相:$appearance,声音:$sound")
    }

    fun test() {
        println(nature) // 编译OK
        println(appearance) // 编译不通过
        println(sound) // 编译不通过
    }
}

init 方法体中可以访问主构造器的所有参数,而方法 test() 却只能访问 var 声明的构造器参数。

  • 主构造器中,使用 var 声明的参数,将成为成员变量,可以在类的各个方法中调用。
  • 而不使用 var 声明参数,只是临时变量,只能在 init 方法体中使用。

#类的继承

子类继承父类,可以获得父类的能力,Kotlin 中使用 : 连接子父类,形成继承关系,同时,父类需要使用 open 关键字修饰:

open class Human(nature: String, appearance: String, sound: String) {
    init {
        println("${this.javaClass.simpleName} 的性格:$nature,长相:$appearance,声音:$sound")
    }
}

class Girl(nature: String, appearance: String, sound: String) : Human(nature, appearance, sound)
class Boy(nature: String, appearance: String, sound: String) : Human(nature, appearance, sound)

从 Java 开发者的角度来讲,Kotlin 中的类默认是 final 类,而使用 open 修饰过的类,会去除 final 关键字。

#子类构造器

上述例子中,无论是 Girl 或是 Boy,它们的主构造器参数都没有使用 var 声明,实事上也不能使用 var 声明,我们可以做个实验:

// 报错:'nature' hides member of supertype 'Human' and needs 'override' modifier
class Boy(var nature: String, appearance: String, sound: String) : Human(nature, appearance, sound)

Boy 主构造器中使用 var 声明 nature,会报错提示 nature 在父类 Human 中是隐藏成员,你需要使用 override 对其修改,那就按提示把 override 关键字加上,但还会报另一个错:

// 报错:'nature' in 'Human' is final and cannot be overridden
class Boy(override var nature: String, appearance: String, sound: String) : Human(nature, appearance, sound)

如果单单对 nature 追加 override 关键字是不够的,因为构造器中的参数默认是 final 修饰过的不可修改变量,需要对父类 Human 主构造器中的 nature 参数再追加 open 关键字来去除这个限制。

open class Human(open var nature: String, var appearance: String, var sound: String) {
    ...
}
class Boy(override var nature: String, appearance: String, sound: String) : Human(nature, appearance, sound)

好了,终于把子类 Boy 的主构造器参数 nature 加上了 var 声明,那这有什么呢?答案是似乎没啥用。

img

因为就算子类 Boy 主构造器参数 nature 不用 var 声明,也一样可以在子类 Boy 的成员方法中使用这个 nature 变量,原因是 nature 早已在父类 Human 的主构造器中使用了 var 声明,它是父类 Human 的成员变量(类似 Java 中的 protected final String nature ),可以被子类 Boy 识别和调用。所以,话说回来,我们什么时候会需要使用 var 来声明与父类构造器参数同名的子类主构造器参数呢?

open class Human(nature: String, var appearance: String, var sound: String) {
    ...
}

class Boy(var nature: String, appearance: String, sound: String) : Human(nature, appearance, sound)

当父类主构造器参数没有使用 var 声明,而子类又需要在成员方法中使用该参数时,可以在子类的构造器中,为该参数使用 var 追加声明,让其成为子类的成员变量。除此之外,子类主构造器参数的使用与普通的主构造器参数没什么区别。

#Any 类

在 Kotlin 中,Any 是所有类的始祖,相当于 Java 中的 Object。

/**
 * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
 */
public open class Any {
    ...
}

#包(Package)

  • 包就是命名空间
  • 包的声明必须在非注释代码的第一行
  • 类的全名是 包名+类名 ,如:com.area.guangzhou.Human

举个例子,在 com.area.guangzhou 包下声明一个 Human 类:

package com.area.guangzhou // 第一行代码:包声明
/**
 * 广州人
 */
class Human {
}

由于包的存在,因此工程中可以在不同的目录下,声明多个类名相同的类,比如在 com.area.shantou 再声明一个 Human 类:

package com.area.shantou
/**
 * 汕头人
 */
class Human {
}

因为类名相同,所以在同个文件中使用时,为了区分 2 个 Human,需要使用类的全名:

fun main(args: Array<String>) {
    val gzHuman = com.area.guangzhou.Human()
    val stHuman = com.area.shantou.Human()
}

这样写出来的代码,看起来很不雅观,这时我们可以使用 as 关键字对导包设置别名:

import com.area.guangzhou.Human as 自给人
import com.area.shantou.Human as 胶己人

fun main(args: Array<String>) {
    val gzHuman = 自给人()
    val stHuman = 胶己人()
}

注意:这里的代码仅为演示说明,实际开发中,为了避免不必要的麻烦,最好不要使用中文进行 coding。

相关文章
|
23天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
16天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
20天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2576 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
18天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
3天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
2天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
163 2
|
20天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1576 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
22天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
972 14
|
3天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
218 2
|
17天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
734 9