【Kotlin】类和对象

news2024/9/23 9:36:38

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.kotlinStudy

class 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 = name
        this.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 类是所有类的基类。

        类的初始化顺序如下。

  1. 父类主构造函数
  2. 父类 init 代码块
  3. 父类次要构造函数
  4. 子类主构造函数
  5. 子类 init 代码块
  6. 子类次要构造函数

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: String
    abstract 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: String
    fun aFun()
}

interface B {
    var y: String
    fun 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1502844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

和数软件:区块链技术的爆发与冲击

什么是区块链?它是如何发展而来的?应用在哪些领域?将会对我国的社会经济产生哪些重大影响? 什么是区块链 区块链作为一种底层技术,最早的实践是数字货币。根据最早的中本聪定义,区块链实质上是一种基于网…

人工智能|机器学习——Canopy聚类算法(密度聚类)

1.简介 Canopy聚类算法是一个将对象分组到类的简单、快速、精确地方法。每个对象用多维特征空间里的一个点来表示。这个算法使用一个快速近似距离度量和两个距离阈值T1 > T2 处理。 Canopy聚类很少单独使用, 一般是作为k-means前不知道要指定k为何值的时候&#…

借助产品说明书模板,让你轻松制作产品说明书

产品说明书是一种普遍存在的文档,在我们日常生活和工作中,您可能需要为自己的产品或服务创建一个。这是因为产品说明书是介绍产品特性、使用说明、维护方式以及注意事项等内容的有效工具。然而,制作产品说明书可能是一个复杂且困难的过程&…

Python实现一个简单的主机-路由器结构(计算机网络)

说明 本系统模拟实现了一个路由器与两个主机节点。该路由器将接收原始以太网帧,并像真正的路由器一样处理它们:将它们转发到正确的传出接口,处理以太网帧,处理 IPv4 分组,处理 ARP分组,处理 ICMP 分组&…

太阳辐射环境模拟系统系统

太阳辐射环境模拟系统是一种高度专业化的设备,用于模拟太阳光的全谱段辐射,包括紫外线、可见光和红外线。这种系统的核心功能是在实验室条件下复制太阳的辐射条件,以评估材料、产品或设备在实际太阳辐射影响下的性能和耐久性。 应用领域&…

2024-03-05 linux 分区老显示满,Use 100%,原因是SquashFS 是一种只读文件系统,它在创建时就已经被填满,所有空间都被使用。

一、这两天一直纠结一个问题,无论怎么修改,linux 分区老显示满,Use 100%,全部沾满。如下图的oem分区。 二、导致出现上面的原因是:SquashFS文件系统里的空间利用率总是显示为100%。 三、SDK里面也说明SquashFS文件系统…

【洛谷 P8668】[蓝桥杯 2018 省 B] 螺旋折线 题解(数学+平面几何)

[蓝桥杯 2018 省 B] 螺旋折线 题目描述 如图所示的螺旋折线经过平面上所有整点恰好一次。 对于整点 ( X , Y ) (X, Y) (X,Y),我们定义它到原点的距离 dis ( X , Y ) \text{dis}(X, Y) dis(X,Y) 是从原点到 ( X , Y ) (X, Y) (X,Y) 的螺旋折线段的长度。 例如 …

武汉灰京文化:手机游戏行业创新与机遇引领着无限潜力的繁荣

近年来,手机游戏行业迎来了前所未有的繁荣,这主要得益于新技术的飞速发展和硬件的不断升级。市场研究机构预测,到2025年,全球手机游戏市场将超过2000亿美元。这一惊人的增长数据充分体现了手机游戏行业的活力和无限潜力。手机游戏…

appium2的一些配置

appium-desktop不再维护之后,需要使用appium2。 1、安装appium2 命令行输入npm i -g appium。安装之后输入appium或者appium-server即可启动appium 2、安装安卓/ios的驱动 安卓:appium driver install uiautomator2 iOS:appium driver i…

21 easy 1. 两数之和

//给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 // // 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 // // 你可以…

代码随想录 回溯算法-棋盘问题

目录 51.N皇后 37.解数独 51.N皇后 51. N 皇后 困难 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n &…

GESP5级T1真题 [202309] 因数分解——O(sqrt(n))的时间复杂度,值得一看

描述 每个正整数都可以分解成素数的乘积&#xff0c;例如&#xff1a;62*3、2022 *5 现在&#xff0c;给定一个正整数N&#xff0c;请按要求输出它的因数分解式。 输入描述 输入第一行&#xff0c;包含一个正整数N。约定2<N<10^12 输出描述 输出一行&#xff0c;为N…

Web APIs 6 正则表达式

Web APIs 6 正则表达式1、介绍2、语法方法一方法二 3、元字符分类① 边界符② 量词③ 字符类 案例&#xff1a;用户名验证 4、修饰符案例&#xff1a;过滤敏感字 案例&#xff1a;小兔鲜注册注册模块 正则表达式 1、介绍 正则表达式&#xff08;Regular Expression&#xff0…

OpenAI (ChatGPT)中国免费试用地址

GitHub - click33/chatgpt---mirror-station-summary: 汇总所有 chatgpt 镜像站&#xff0c;免费、付费、多模态、国内外大模型汇总等等 持续更新中…… 个人能力有限&#xff0c;搜集到的不多&#xff0c;求大家多多贡献啊&#xff01;众人拾柴火焰高&#xff01;汇总所有 cha…

uniapp模仿下拉框实现文字联想功能 - uniapp输入联想(官方样式-附源码)

一、效果 废话不多说&#xff0c;上效果图&#xff1a; 在下方的&#xff1a; 在上方的&#xff1a; 二、源码 一般是个输入框&#xff0c;输入关键词&#xff0c;下拉一个搜索列表。 ElementUI有提供<el-autocomplete>&#xff0c;但uniapp官网没提供这么细&#x…

基于Vue的实时影片资讯APP设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 Vue框架 3 1.2 MVVM 3 1.3 Mongodb数据库 4 1.4 Axios请求 4 1.5 H5、CSS3和JavaScript 5 1.6 本章小结 5 2 系统分析 7 2.1 功能需求 7 2.2 用例分析 7 2.3 用户功能 8 2.4本章小结 8 3 Vue影片票务服务APP设计 9 3.1 页…

基于华为atlas的unet分割模型探索

Unet模型使用官方基于kaggle Carvana Image Masking Challenge数据集训练的模型。 模型输入为572*572*3&#xff0c;输出为572*572*2。分割目标分别为&#xff0c;0&#xff1a;背景&#xff0c;1&#xff1a;汽车。 Pytorch的pth模型转化onnx模型&#xff1a; import torchf…

【蓝桥杯】单词分析 (BF)

一.题目描述 二.问题分析 //单词分析 #include <iostream> using namespace std;const int N1e42; char s[N]; int c[26]{0};int main(int argc, const char * argv[]) {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>s;int max0,i0;char xa;while(s[i]){…

【Python使用】python高级进阶知识md总结第1篇:My Awesome Book【附代码文档】

python高级进阶全知识知识笔记总结完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;My Awesome Book&#xff0c;My Awesome Book。My Awesome Book&#xff0c;MySQL数据库。My Awesome Book&#xff0c;聚合函数。My Awesome Book&#xff0c;创建表并给…

Mysql深入学习 基础篇 Ss.06 事务

青青子衿&#xff0c;悠悠我心 纵我不往&#xff0c;子宁不嗣音 —— 24.3.9 事务&#xff1a; 事务简介 事务操作 事务四大特性 并发事务问题 事务隔离级别 一、事务简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整…