【Kotlin】类和对象
1 前言
Kotlin 是面向对象编程语言,与 Java 语言类似,都有类、对象、属性、构造函数、成员函数,都有封装、继承、多态三大特性,不同点如下。
- Java 有静态(static)代码块,Kotlin 没有;
- Java 有静态(static)函数,Kotlin 没有;
- Java 构造函数名与类名相同,Kotlin 构造函数名为 constructor;
- Kotlin 有初始化代码块(init),Java 没有;
- Kotlin 有主构造函数,Java 没有。
在包下面右键,依次点击【New → Kotlin Class/File】,输入类名后,创建 Kotlin 类文件。

如下,创建了一个 Student.kt 文件。
package com.zhyan8.kotlinStudyclass Student {
}
笔者为简化代码,将定义的类与 main 函数放在同一个文件中了。
2 类的结构
如下,Student 类是一个自定义的类,里面包含了一个类的基本结构。
fun main() {var stu1 = Student()stu1.study()println("-----------------------------------------")var stu2 = Student("li si", 23)
}class Student {private var name: String = "zhang san" // 属性get() { // name的getter函数return field}set(value) { // name的setter函数field = value}private var age: Int = 18 // 属性init { // 初始化代码块, 在构造函数前执行println("Student init, name=$name, age=$age")}constructor() { // 无参构造函数println("create-1, name=$name, age=$age")}constructor(name: String, age: Int) { // 有参构造函数println("create-2, name=$name, age=$age")this.name = namethis.age = age}fun study() { // 成员函数println("study...")}
}
说明:init 代码块可以有多个,按照从前往后的顺序执行;上述构造函数都是次要构造函数,第 3 节中会介绍主构造函数。
运行程序后,打印如下。
Student init, name=zhang san, age=18
create-1, name=zhang san, age=18
study...
-----------------------------------------
Student init, name=zhang san, age=18
create-2, name=li si, age=23
3 主构造函数
主构造函数是紧接在类名后面的构造函数,次要构造函数是类体内部定义的构造函数,它们的区别如下。
- 主构造函数:主构造函数只能存在一个,只有函数声明,没有函数体,可以在入参中定义类的属性,会自动进行类属性的初始化赋值。
- 次要构造函数:次要构造函数可以存在多个,可以自定义函数体,也可以无函数体,不能在入参中定义类属性,当类有主构造函数时,所有次要构造函数必须直接或间接地调用主构造函数。
3.1 无参主构造函数
fun main() {var stu1 = Student()println("-----------------------------------------")var stu2 = Student("zhang san")
}class Student() { // 等价与: class Student constructor()init { // 初始化代码块, 在构造函数前执行println("init")}constructor(name: String): this() {println("constructor, name=$name")}
}
运行程序后,打印如下。
init
-----------------------------------------
init
constructor, name=zhang san
class Student() 等价于 class Student constructor(),如果需要对主构造函数的权限进行控制,可以修改如下。
class Student private constructor() {...
}
3.2 有参主构造函数(普通参数)
fun main() {var stu1 = Student("xiao ming", 23)println("-----------------------------------------")// stu1.name // 编译报错, name不是成员属性var stu2 = Student()
}class Student(name: String, age: Int) {init {println("init, name=$name, age=$age")}constructor(): this("zhang san", 18) {println("constructor")}
}
运行程序后,打印如下。
init, name=xiao ming, age=23
-----------------------------------------
init, name=zhang san, age=18
constructor
3.3 有参主构造函数(成员属性)
fun main() {var stu1 = Student("xiao ming", 23)println("stu1.name=${stu1.name}, stu1.age=${stu1.age}")println("-----------------------------------------")var stu2 = Student()println("stu2.name=${stu2.name}, stu2.age=${stu2.age}")
}class Student(var name: String, var age: Int) {init {println("init, name=$name, age=$age")}constructor(): this("zhang san", 18) {println("constructor")}
}
说明:在主构造函数中,通过给入参添加 var(变量)或 val(常量)修饰,使得参数变为成员属性;在次要构造函数中,不能给入参添加 var 或 val 修饰。
运行程序后,打印如下。
init, name=xiao ming, age=23
stu1.name=xiao ming, stu1.age=23
-----------------------------------------
init, name=zhang san, age=18
constructor
stu2.name=zhang san, stu2.age=18
如果用户想修改入参属性的权限,可以在 var 或 val 前面添加权限修饰符。
class Student(private val name: String, protected var age: Int) {...
}
4 封装
封装是指将相关联的属性和函数封装到同一个类中,并且可以控制这些属性和函数的访问权限,它通过隐藏内部细节和提供清晰的接口,提高了代码的安全性、可维护性和可理解性,它是面向对象编程中的重要概念之一。
在 Kotlin 中,有四种访问权限修饰符:private、protected、internal 和 public。这些修饰符控制了代码中类、函数、属性等成员的可见性和访问权限。
- private:最严格的访问权限,只在声明它的类或文件内可见。
- protected:与 Java 中的 protected 类似,不同之处在于 Kotlin 中 protected 修饰的成员仅对其子类可见,但不一定在同一个文件中可见。另外,protected 在 Kotlin 中不能直接应用于顶层函数和属性(直接定义在文件中的函数和属性,而不是在类中定义的)。
- internal:模块内可见(模块是编译在一起的一组 Kotlin 文件),internal 修饰的成员对于同一模块中的任何其他代码都是可见的,但对于其他模块中的代码是不可见的。
- public:最宽松的访问权限,public 成员可以被任何地方的代码访问,如果没有指定访问修饰符,默认为 public。
5 继承
继承是指一个类(称为子类或派生类)基于另一个类(称为父类或基类)创建新类,子类继承了父类的属性和函数,并且可以在此基础上进行扩展或修改,它是面向对象编程中的重要概念之一。在 Kotlin 中,继承使用冒号(:)来表示,Any 类是所有类的基类。
类的初始化顺序如下。
- 父类主构造函数
- 父类 init 代码块
- 父类次要构造函数
- 子类主构造函数
- 子类 init 代码块
- 子类次要构造函数
5.1 子类无主构造函数
fun main() {var stu = Student("zhang san", 23, 1001)
}open class People(var name: String) {init {println("People init, name=$name") // 1}constructor(name: String, age: Int): this(name) {println("People constructor, name=$name, age=$age") // 2}
}class Student : People {init {println("Student init, name=$name") // 3 (此处不能访问age和id)}constructor(name: String, age: Int, id: Int) : super(name, age) {println("Student constructor, name=$name, age=$age, id=$id") // 4}
}
说明:子类必须直接或间接调用一下父类的一个构造函数,否则编译报错。
运行程序后,打印如下。
People init, name=zhang san
People constructor, name=zhang san, age=23
Student init, name=zhang san
Student constructor, name=zhang san, age=23, id=1001
5.2 子类有主构造函数
fun main() {var stu = Student("zhang san", 23, 1001)
}open class People(var name: String) {init {println("People init, name=$name") // 1}constructor(name: String, age: Int): this(name) {println("People constructor, name=$name, age=$age") // 2}
}class Student(name: String, var age: Int) : People(name, age) {init {println("Student init, name=$name, age=$age") // 3 (此处不能访问id)}constructor(name: String, age: Int, id: Int): this(name, age) {println("Student constructor, name=$name, age=$age, id=$id") // 4}
}
说明:子类必须直接或间接调用一下父类的一个构造函数,否则编译报错;当子类中有主构造函数时,子类中的次要构造函数。
运行程序后,打印如下。
People init, name=zhang san
People constructor, name=zhang san, age=23
Student init, name=zhang san, age=23
Student constructor, name=zhang san, age=23, id=1001
6 多态
多态是指同一个函数可以在不同的对象上表现出不同的行为,这种行为通常通过继承和接口来实现。多态使得代码更加灵活和可扩展,是面向对象编程中的重要概念之一。
6.1 覆盖函数
fun main() {var peo: People = Student("li si", 25, 1002)peo.say()
}open class People(var name: String, var age: Int) {init {println("People init, name=$name, age=$age")}open fun say() {println("People say")}
}class Student(name: String, age: Int, var id: Int) : People(name, age) {init {println("Student init, name=$name, age=$age, id=$id")}override fun say() {println("Student say")}
}
运行程序后,打印如下。
People init, name=li si, age=25
Student init, name=li si, age=25, id=1002
Student say
6.2 覆盖属性
fun main() {var peo : People = Student()peo.doSomething()
}open class People {open var name: String = "zhang san"fun doSomething() {println("doSomething, name=$name")}
}class Student : People() {override var name: String = "li si"
}
运行程序后,打印如下。
doSomething, name=li si
6.3 类型智能转换
fun main() {var peo: People = Student()// peo.study() // 编译报错if (peo is Student) {peo.study() // 智能转换为Student}
}open class People {
}class Student : People() {fun study() {println("study...")}
}
说明:Java 没有智能转换特性,需要进行强制类型转换。
7 抽象类
使用 abstract 修饰的类称为抽象类,抽象类中可以有抽象属性和函数,这些属性和函数被添加了 abstract 修饰符,父类不能实现,子类必须重写实现(子类如果也是抽象类除外)。抽象类不能被实例化,只能实例化其具化子类,抽象类中允许有具化的属性和函数。
fun main() {// var peo = People() // 编译报错, 抽象类不能被实例化var stu = Student()stu.say()
}abstract class People {abstract var name: Stringabstract fun say()
}class Student : People() {override var name: String = "xiao min"override fun say() {println("$name: Hello")}
}
说明:Java 中只有抽象函数,没有抽象属性。
运行程序后,打印如下。
xiao min: Hello
8 接口
接口与抽象类有些类似,接口里只有抽象属性和函数(函数允许有默认实现,属性不能),Kotlin 中允许一个类实现多个接口,但最多只能继承一个类。
fun main() {var c = C("xxx", "yyy")c.aFun()c.bFun()
}interface A {var x: Stringfun aFun()
}interface B {var y: Stringfun bFun()
}class C(override var x: String, override var y: String) : A, B {override fun aFun() {println("aFun, x=$x")}override fun bFun() {println("bFun, y=$y")}
}
运行程序后,打印如下。
aFun, x=xxx
bFun, y=yyy相关文章:
【Kotlin】类和对象
1 前言 Kotlin 是面向对象编程语言,与 Java 语言类似,都有类、对象、属性、构造函数、成员函数,都有封装、继承、多态三大特性,不同点如下。 Java 有静态(static)代码块,Kotlin 没有࿱…...
Docker完整版(一)
Docker完整版(一) 一、Docker概述1.1、Docker简介1.2、Docker的用途1.3、容器与虚拟机的区别1.4、Docker系统架构1.5、Docker仓库 二、Docker引擎2.1、Docker引擎架构2.2、Docker引擎分类2.3、Docker引擎的安装2.4、Docker镜像加速器 三、Docker镜像3.1、…...
AIOPS:Zabbix结合讯飞星火做自动化告警+邮件通知并基于人工智能提供解决方案
目前Zabbix官方已经提供Zabbix+ChatGPT的解决方案 ChatGPT一周年,你充分利用了吗?Zabbix+ChatGPT,轻松化解告警! 但是由于需要魔法等其他因素,比较不稳定,遂决定使用国内模型,这里我挑选的是讯飞星火,基于我之前的文档,在此基础上通过Zabbix的告警脚本实现调用AI模型…...
AHU 汇编 实验六
一、实验名称:实验6 输入一个16进制数,把它转换为10进制数输出 实验目的: 培养汇编中设计子程序的能力 实验过程: 源代码: data segmentbuff1 db Please input a number(H):$buff2 db 30,?,30 dup(?),13,10buff3 …...
Linux的输出、输入重定向和管道
目录 输出重定向 输入重定向 < << 管道操作 输出重定向 当我输⼊⼀个命令之后,回⻋,命令产⽣了结果,结果默认是输出到屏幕上的。 默认情况,⽆论⼀个命令执⾏正确与否,结果都会默认输出到屏幕上。 在有…...
java-新手笔记(枚举)
枚举(Enumeration)是一种特殊的类,用于表示固定数量的常量值。 枚举类型使得代码更加清晰,易于维护,同时也增加了类型安全。 这边使用一个枚举封装重要数据 enum Day {SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FR…...
Centos7 安装postgresql14后无法连接数据库
1、数据库服务器允许外部访问5432端口。 2、postgresql.conf 3、pg_hba.conf a、制定某个IP(192.168.0.107)访问 b、指定ip段访问 允许10.1.1.0~10.1.1.255网段登录数据库 host all all 10.1.1.0/24 trust c、指定全网访问 host a…...
GaussDB(DWS)运维利刃:TopSQL工具解析
在生产环境中,难免会面临查询语句出现异常中断、阻塞时间长等突发问题,如果没能及时记录信息,事后就需要投入更多的人力及时间成本进行问题的定位和解决,有时还无法定位到错误出现的地方。在本期《GaussDB(DWS)运维利刃࿱…...
信息安全、网络安全以及数据安全三者之间的区别
随着信息技术的飞速发展,网络安全、信息安全、数据安全等词汇在平时出现的频率越来越高,尤其是数据安全,是大家都关心的一个重要话题。事实上,有很多人对网络安全、信息安全、数据安全的概念是区分不清的,下面由我帮大…...
初阶数据结构之---堆的应用(堆排序和topk问题)
引言 上篇博客讲到了堆是什么,以及堆的基本创建和实现,这次我们再来对堆这个数据结构更进一步的深入,将讲到的内容包括:向下调整建堆,建堆的复杂度计算,堆排序和topk问题。话不多说,开启我们今…...
架构师面试100问?
面试架构师时,需要考察广泛的知识领域,包括技术、架构设计、团队管理、沟通能力等方面。以下是一些可能的面试问题,涵盖了多个方面问题: 介绍一下你的技术背景和经验。你在之前的项目中扮演过哪些角色?你对微服务架构…...
visualization_msgs::Marker 的pose设置,map坐标系的3d box显示问题
3D框显示 3D框显示可以使用visualization_msgs::Marker::LINE_LIST或者LINE_STRIP,前者使用方法需要指明线的两个端点,后者自动连接相邻两个点。 姿态问题 网上看了一些,没有涉及到朝向设置,Pose.orientation默认构造为4个0 至…...
c语言:输入定制
输入定制 任务描述 输入数据是一大串数字,要求读取五个数,但要求你只处理其中的第1、3、5个数,输出这三个数的和。第一个数只读1位数,第二个数只读2位数,第三个数只读3位数,第四个数只读4位数,…...
Python批量提取Word文档表格数据
在大数据处理与信息抽取领域中,Word文档是各类机构和个人普遍采用的一种信息存储格式,其中包含了大量的结构化和半结构化数据,如各类报告、调查问卷结果、项目计划等。这些文档中的表格往往承载了关键的数据信息,如统计数据、项目…...
【Qt】四种绘图设备详细使用
绘图设备有4个: 绘图设备是指继承QPainterDevice的子类—QPixmap QImage QPicture QBitmap(黑白图片) QBitmap——父类QPixmapQPixmap图片类,主要用来显示,它针对于显示器显示做了特殊优化,依赖于平台的,只能在主线程中使用(UI线…...
区块链web3智能合约Solidity学习资源整理
简单说明: Solidity 是一门面向合约的、为实现智能合约而创建的高级编程语言。这门语言受到了 C,Python 和 Javascript 语言的影响,设计的目的是能在以太坊虚拟机(EVM)上运行。 Solidity中文官方文档: ht…...
python学习、开发实用文档分享
今天给大家分享两个好用的关于python django框架使用的在线文档 Django中文在线文档: Django 文档 | Django 文档 | Django django rest framework 文档 1 - Serialization - Django REST framework中文站点 有开发和学习中遇到不会的, 或者需要学习的技能点直接去上面两个…...
Docker compose部署redis哨兵集群
Docker compose部署redis哨兵集群 安装Docker和docker-compose准备docker-compose文件redis exporter本地部署准备Redis配置文件ACL用户权限配置Linux内核参数优化启停Redis实例主从复制配置 环境准备: IP版本角色172.x.x.11RHEL 7.9master172.x.x.12RHEL 7.9repli…...
Python 导入Excel三维坐标数据 生成三维曲面地形图(面) 4-1、线条平滑曲面(原始图形)
环境和包: 环境 python:python-3.12.0-amd64包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 scipy 1.12.0 代码: import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.interpolate import griddata fro…...
有趣的数学 毕达哥拉斯定理
随便找个学生,让他举出一位著名的数学家——如果他能想到的话,他往往会选择毕达哥拉斯。如果不是,也许他想到的是阿基米德。哪怕是杰出的艾萨克牛顿,在两位古代世界的巨星面前也只能叨陪末座了。阿基米德是一位思想巨人࿰…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
