Kotlin学习历程——类的定义

Kotlin 9. Kotlin Class:数据类(data class),枚举类(Enum Class),密封类(Sealed Class) 在这篇博客中,我们将详细介绍 Kotlin 各种类,包括类的构造函数,数据类(data class),枚举类(Enum Class),密封类(Sealed Class)。 阅读详情

Kotlin语言中文站

定义类

Kotlin中使用关键字class声明一个类,类声明由类名、类头(指定其类型参数、主构造函数等)以及由花括号包围的类体构成。 类头、类体是可选的,如果一个类没有类体,可以省略花括号。

//声明Person类
class Person { /* .... */ }

//没有类体,可以省略花括号
class Person

构造函数

在kotlin中一个类可以有一个或者没有主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分,它跟在类名(与可选的类型参数)后面。

//携带主构造函数的Person类
class Person constructor(firstname: String) { /* ... */ }

//如果主构造函数没有任何注解或者可见性修饰符,可以省略 constructor 关键字
class Person(firstname: String) { /* ... */ }

主构造函数不能包含任何的代码,那如果我想增加一些初始化代码怎么办? kotlin中的初始化块 init 应运而生。

初始化块(initializer blocks)
class Person(firstname: String) {
    //主构造器的参数firstname也可以在类体内声明的属性初始化器中使用
    val propertyOne = "propertyOne##firstname:$firstname.".also { println(it) }

    //初始化块1
    init {
        //这里可以使用主构造器的参数firstname
        println("init1##firstname:$firstname.")
    }

    //主构造器的参数firstname也可以在类体内声明的属性初始化器中使用
    val propertyTwo = "propertyTwo##firstname:$firstname.".also { println(it) }
    
    //初始化块2
    init {
        //这里可以使用主构造器的参数firstname
        println("init2##firstname:$firstname.") 
    }
}

//执行上面的代码
fun main(args: Array<String>) {
    Person("hepingdev")
}


//打印结果
propertyOne##firstname:hepingdev.
init1##firstname:hepingdev.
propertyTwo##firstname:hepingdev.
init2##firstname:hepingdev.

如上,一个类可以有一个或多个初始化块,初始化块按照它们出现在类体中的顺序执行,与属性初始化器优先级一样。 这里我们不妨把上面的代码转成Java代码,看看init到底是个啥?

public final class Person {
   @NotNull
   private final String propertyOne;
   @NotNull
   private final String propertyTwo;

   @NotNull
   public final String getPropertyOne() {
      return this.propertyOne;
   }

   @NotNull
   public final String getPropertyTwo() {
      return this.propertyTwo;
   }

   //主构造函数
   public Person(@NotNull String firstname) {
      super();
      String var2 = "propertyOne##firstname:" + firstname + '.';
      System.out.println(var2);      ----> 打印属性1
      this.propertyOne = var2;
      var2 = "init1##firstname:" + firstname + '.';
      var3 = false;
      System.out.println(var2);     ----> 打印初始化块1
      var2 = "propertyTwo##firstname:" + firstname + '.';
      System.out.println(var2);       ----> 打印属性2
      this.propertyTwo = var2;
      var2 = "init2##firstname:" + firstname + '.';
      System.out.println(var2);     ----> 打印初始化块2
   }
}

由上可知,它的作用就是在主构造函数里面增加操作性代码,即初始化块中的代码实际上会成为主构造函数的一部分。

次构造函数

类中声明前缀有constructor 的次构造函数。

class Person {
    //次构造函数
    constructor(secondname:String, modifydata:String) {
        println("secondname:$secondname modifydata:$modifydata")
    }
}

次构造函数可以简单理解:解决kotlin中只能定义一个主构造函数的缺陷,毕竟开发中类会存在多个构造器的需求。

如果类有主构造函数,每个次构造函数必须委托给主构造函数(否则会编译报错),可直接委托或者通过别的次构造函数间接委托,通过关键字this进行委托。

class Person(name:String) {

    init {
        println("init####.")
    }

    constructor(name:String, age: Int) : this(name, age, "") {
        println("constructor##间接委托")
    }

    constructor(name: String, age: Int, address: String) : this(name) {
        println("constructor##直接委托")
    }
}

没有主构造函数,虽然不用显式声明委托,但实际仍会隐式发生委托,从如下代码打印结果可看出:

class Person {
    init {
        println("init####.")
    }

    constructor(name:String, age: Int) {
        println("constructor##2")
    }

    constructor(name: String, age: Int, address: String) {
        println("constructor##3")
    }
}


fun main(args: Array<String>) {
    Person("hepingdev", 100, "中国")//打印什么?
    //打印结果
    init####.
    constructor##3
    
    
    Person("hepingdev", 100)//打印什么?
    //打印结果
    init####.
    constructor##2
}

上面说到,初始化块实际上会成为主构造函数的一部分,委托给主构造函数会作为次构造函数的第一条语句,因此所有初始化块与属性初始化器中的代码都会在次构造函数之前执行。即使类没有主构造函数,这种委托仍会隐式发生,并且仍会执行初始化块。

如果一个非抽象类没有声明任何(主/次)构造函数,那么会自动生成一个不带参数的主构造函数:

//kotlin类
class Person

//java代码如下
public final class Person {
    //一般默认不写
    public Person(){} 
}

声明属性

类中声明属性kotlin有个简洁的写法:

class Person(var name:String, var age: Int, var address: String) { ... }

上面是在主构造函数声明,当然也可以在类体中声明:

class Person {
    var name:String = ""
    var age: Int = 0
    var address:String=""
}

转成Java代码如下所示:

/**  主构造函数声明 */
public final class Person {
   @NotNull
   private String name;
   private int age;
   @NotNull
   private String address;

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      this.name = var1;
   }

   public final int getAge() {
      return this.age;
   }

   public final void setAge(int var1) {
      this.age = var1;
   }

   @NotNull
   public final String getAddress() {
      return this.address;
   }

   public final void setAddress(@NotNull String var1) {
      this.address = var1;
   }

   public Person(@NotNull String name, int age, @NotNull String address) {
      this.name = name;
      this.age = age;
      this.address = address;
   }
}


/**   类体中声明    */
public final class Person {
   @NotNull
   private String name = "";
   private int age;
   @NotNull
   private String address = "";

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      this.name = var1;
   }

   public final int getAge() {
      return this.age;
   }

   public final void setAge(int var1) {
      this.age = var1;
   }

   @NotNull
   public final String getAddress() {
      return this.address;
   }

   public final void setAddress(@NotNull String var1) {
      this.address = var1;
   }
}

两种写法没啥区别。

创建类的实例

注意 Kotlin 没有 new关键字。

//无参构造函数
val p = Person()

//携带参数的构造函数
val p = Person("hepingdev", 100, "中国")

次构造函数,初始化块,属性初始化器执行顺序?

如下代码, 打印什么?

class Person(name: String, age: Int) {

    var name: String = "i am $name, $age years old.".also { println(it) }

    init {
        println("init####.")
    }

    constructor(name: String, age: Int, address: String):this(name, age) {
        println("constructor##i am $name, $age years old, from $address")
    }
}


fun main(args: Array<String>) {
    //调用主构造函数
    Person("hepingdev", 100) //打印什么
    //打印如下
    //i am hepingdev, 100 years old.
    //init####.
    
    
    //调用次构造函数
    Person("hepingdev", 100, "中国")//打印什么
    //打印如下
    //i am hepingdev, 100 years old.
    //init####.
    //constructor##i am hepingdev, 100 years old, from 中国
}

根据打印结果,结论如下:

  • 调用主构造函数初始化: super() -> init() / 属性初始化器
  • 调用次构造函数初始化: super() -> init() / 属性初始化器 -> 次构造函数

下一篇:Kotlin学习历程——继承。

Kotlin基础——类、对象和接口 kotlin中同样使用interface关键字来定义接口,接口的含义和Java中类似,用于定义抽象使用interface关键字定义接口。实现一个接口跟Java中不同,Kotlin中继承类和实现接口都是使用冒号。重写接口中的方法,使用override关键字,与Java中不同的是,override是必须写的,如果不写则会报错。这会避免先写出实现方法再添加抽象方法造成的意外重写。和Java一样,Kotlin中的类只能继承一个类,但可以实现多个方法。 阅读详情

相关推荐

mmkv跨进程,Android开发经验的有效总结,系列篇

前言 笔者看了一些NDK的项目。一些教程不是HelloWord就是直接整FFmpeg或OpenCV,可谓一个天一个地,而且目录结构和Android3.5的默认结构并不是太一致,一直没找到什么合心的文章。故写此文连接这天地,来总结一下在NDK开发之前你应知道的东西。 在此之前,先划分三类人,如果不认清自己是什么角色就去玩NDK,你会很糟心: user : 纯粹.so链接库使用者(伸手党) creator : 纯粹ndk开发者,创作.so链接库(创作家) designer : 在现有的.so上自.

m0_56004877的博客 660

kotlin基础--类定义、初始化、继承

上次介绍了kotlin中的集合List、Set、Map的操作,接下来介绍kotlin中如何定义类、初始化、继承 一、类的定义 1.field 对于每个属性,kotlin会自动生成一个的field:代表属性的值,一个getter方法,一个setter方法。我们操作属性时,实际调用的是get和set方法,因为kotlin变量的不可空性,对于非空变量,我们在赋值时,系统要对赋值的值进行是否为null判断...

aruba的博客 1136

Java云上香云祭祀线上祭祀系统小程序源码

云上香云祭祀线上祭祀系统”,不仅是一种祭祀方式的创新,更是对传统文化的一次深情致敬。它让我们明白,无论时代如何变迁,对亲人的怀念与尊重永远不会改变。在这个特别的平台上,让我们共同守护那份跨越时空的爱与思念,让心灵得以安放,让生命之树常青。🌳。

2401_84413757的博客 804

Kotlin学习笔记——类、接口、扩展方法、空类型

定义类和构造方法: class SimpleClass(var x: Int, val y: String){} //创建类不需要new关键字 val simpleClass = SimpleClass(9, "Hello") 构造方法放在类名的后面,如果x和y前面加了var或val, x和y会分别在类中定义一个属性以及对应的getter和setter方法,不需要额外写,否则必须手动写getter和setter实现。类前面不需要修饰符public private等,跟java不一样,默认是publi.

川峰的博客 887

android mtk camera如何自定义默认拍照与录像分辨率

本文详细解析了在Android MTK平台上自定义相机默认拍照与录像分辨率的方法。通过分析Camera2应用默认选择逻辑,定位并修改PictureSize.java与VideoQualityCaptureRequestConfig.java中的关键代码,实现绕过系统智能选择,强制指定最高或特定分辨率。文章还提供了进阶的可配置化方案与验证避坑指南,帮助开发者精准控制相机行为。

weixin_29194817的博客 433

ZynqMP多核实战:如何让A53-0跑Linux,其他核裸机处理大数据(附完整配置流程)

本文详细解析了Xilinx ZynqMP多核异构计算实战,重点介绍如何配置A53-0运行Linux系统,同时让其他A53和R5核心以裸机方式处理大数据任务。内容涵盖内存划分、核间通信、Linux定制配置等关键技术,提供完整的配置流程和性能优化方案,助力开发者实现高效的多核协同开发。

weixin_30555125的博客 479

三、Kotlin 类型初步

JavaKotlinclass Foo注意:类的访问权限修饰符默认为public。若类的{}为空,可以省略不写。JavaKotlinval x: Int = 0 // 需要显示初始化Java中定义类中的成员属性时,不需要显示初始化,会有一个默认值。但是,Kotlin中定义成员属性时,需要显示初始化。Kotlinval x: Intconstructor(x: Int) { // 副构造器(secondary constructor)this.x = x。

zengkaiqiang562的博客 1251

抄表程序员的DLMS/COSEM协议实战:从抓包到解析,手把手教你读懂IEC62056报文

本文深入解析DLMS/COSEM协议在智能电表通信中的应用,从报文捕获到数据解析的全流程实战指南。涵盖HDLC帧解析、应用层连接建立、数据请求/响应解码等核心内容,并提供Wireshark配置、OBIS代码速查表等实用工具,帮助开发者快速掌握IEC62056标准下的电能表通信技术。

weixin_29178069的博客 299

Kotlin学习历程——扩展

Kotlin语言中文站 kotlin能够扩展一个类的新功能而无需继承该类,这种方式叫做扩展。例如:你可以为一个你不能修改的,来自第三方库中的类编写一个新的函数,这个新增的函数就像那个原始类本来就有的函数一样。 定义扩展函数 声明一个扩展函数,我们需要用一个接收者类型也就是被扩展的类型来作为他的前缀。 /** 在Extension.kt文件中定义扩展函数 */ fun <T> MutableList<T>.swap(index1: Int, index2: Int) { .

hepingdev的专栏 2278

告别Windows!Oculus Quest 2在Mac M1上的串流实战(scrcpy+SideQuest避坑指南)

本文为Mac M1用户提供了Oculus Quest 2在macOS上实现高清低延迟串流的实战指南。通过使用开源工具scrcpy和SideQuest,绕开官方限制,详细讲解了从环境准备、无线调试到画质与延迟优化的完整步骤,重点解决了Apple Silicon芯片Mac的连接与性能问题,助你告别Windows依赖。

weixin_29224309的博客 308

构建 Skill 的完整指南

Skill开发指南摘要 Skill是用于定制Claude AI行为的指令包,包含SKILL.md主文件及可选脚本、参考文档和资源。本文提供了完整的Skill开发指南: 核心概念 三层渐进式披露结构(元数据/主指令/参考文档) 支持独立工作流和MCP集成 跨平台兼容性(Claude.ai/ClaudeCode/API) 开发流程 规划:明确2-3个具体用例 结构要求:kebab-case命名、必备YAML元数据 编写规范:清晰触发条件、分步指令、错误处理 典型应用模式 • 文档生成(类别1) • 工作流自动化

wjianwei666的专栏 298

Kotlin学习历程——继承

在Kotlin中所有类都有一个共同的父类Any,这对于没有父类声明的类是默认父类。这跟Java是类似的,只不过在Java中默认父类是Object。 这里我们看看Any类源码: public open class Any { /** * Indicates whether some other object is "equal to" this one. Implementations must fulfil the following * requirements: *

hepingdev的专栏 1394

MATLAB离线附加功能包下载与安装教程

本文介绍如何下载与安装MATLAB离线附加功能包,便于大家更加高效的使用MATLAB。

加斯顿工程师的博客 1万+

Kotlin学习基础知识大全(上)

Kotlin是由JetBrains公司开发的一种静态类型编程语言,最初发布于2011年。JetBrains是知名IDE工具IntelliJ IDEA的开发商,他们开发Kotlin的目的是为了解决Java语言在开发效率、代码简洁性和安全性方面的一些不足。2016年2月,Kotlin 1.0正式发布,标志着语言进入稳定阶段。2017年5月,在Google I/O大会上,Google宣布Kotlin成为Android开发的官方支持语言,这一决定极大地推动了Kotlin的普及。Kotlin中使用fun。

百锦再的博客 1万+

面试官连夜整理:103道AI Agent面试题,答对一半直接加薪50%

维度AutoGPTLangGraphAutoGen控制流LLM 驱动的隐式循环代码层定义的显式状态图对话驱动的自动流转状态存储Prompt 上下文中(易丢失)结构化 State 对象(可持久化)对话历史(自动累积)分支能力依赖 LLM 的文本输出(不稳定)条件边 + 节点路由(确定性)多 Agent 对话自然分支(涌现式)回溯/回滚无原生支持,只能重新开始原生 Checkpoint 支持时间旅行无全局回滚,单 Agent 可重启人机协同仅人工在关键点介入(需要自定义)原生支持。

weixin_35774598的博客 622

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Kotlin学习历程——泛型

Kotlin语言中文站 简单回顾Java泛型 泛型是什么 Java在JDK5中引入了泛型机制。 它的意思可以理解为把具体的类型 参数化,编码时用符号代替类型,实际使用的时候再传入确定的类型,可以用在类、接口或者方法上面。 那么泛型的作用是什么呢?先看一段代码。 public final class Main { public static void main(String[] args) { /** * 案例场景 * * 同事.

hepingdev的专栏 2357

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

分享下学习Kotlin的历程-访问作用域/类修饰词/继承

转载请注明出处:王亟亟的大牛之路开篇之前还是老规矩,先安利https://github.com/ddwhan0123/Useful-Open-Source-Android 还是尽量每天做更新和维护java中访问作用域与继承等姿势很好的对我们的代码进行了封装,那么Kotlin中又是如何定义的呢?这一篇,通过一个简单的demo来讲一下相关知识访问作用域访问作用域也叫访问权限修饰符 通过修饰符来控制类

王亟亟的博客 2729

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Kotlin学习历程

jiangyinglong123456的博客 117

Kotlin学习历程——抽象类与接口

Kotlin语言中文站 Kotlin接口可以即包含抽象方法的声明也包含实现。与抽象类不同的是,接口无法保存状态。它可以有属性但必须声明为抽象或提供访问器实现。 定义接口 使用关键字interface来定义一个接口: interface A { //有函数体的函数 fun foo() { println("A##foo") } //待实现的函数 fun bar() } 实现接口 一个类可以实现一个或者多个接口。 class C : A { .

hepingdev的专栏 1612

Kotlin学习历程一:Kotlin开发安卓的初体验

1.告别findViewById 不同于 JAVA 中,在 Kotlin 中 findViewById 本身就简化了很多,这得益于 Kotlin 的类型推断以及转型语法后置: val onlyTv = findViewById(R.id.onlyTv) as TextView 在官方库Anko的支持下,可以更简化 当你试图 command/ctrl + 左键点击 onlyTv 想要查...

LeeKumaの技术Note 3197

Kotlin学习历程五:kotlin中的类的使用

一、类的声明 关键字 声明类的关键字为class 声明格式 class Test{ // 属性... ... // 构造函数 ... // 函数 ... // 内部类 ... ... } 当类没有结构体的时候,大括号可以省略。即: class Test   二、类的构造函数 在Kotlin中,允许有一个主构...

LeeKumaの技术Note 682

Kotlin学习历程——嵌套类与内部类

Kotlin语言中文站 嵌套类 与Java类似,在Kotlin中类与类可以互相嵌套,类与接口也可以互相嵌套。 class LoginContract { private val TAG = javaClass.simpleName class Presenter : BasePresenter<View>() { fun login(username: String, pwd: String) { //取不到TAG常量 .

hepingdev的专栏 1197

分享下学习Kotlin的历程-环境/简单使用

转载请注明出处:王亟亟的大牛之路从4月开始到现在 一直都在忙React-Native项目的事,途中基本没碰安卓代码,Kotlin这一块之前张涛/医生他们这些先行者开始写文章的时候就已经有所了解,直至”上位”后也没时间静下来钻研,最近逼着自己要静下心来攻克一下,所以写点东西记录一下。内容各平台也许有重复的,我也不首发,只是自己的理解和整理,键盘侠就不要装逼了,谢谢在”旧”的编译器Eclipse也做了支

王亟亟的博客 1112

Kotlin笔记35——定义接口

Kotlin定义接口 举例简单声明一个接口: interface IView { fun show() fun hide() } 实现上面的接口: class Demo9 : IView { override fun show() = println("视图显示了") override fun hide() =println("视图隐藏了") } fun ...

裕博的博客 586

Kotlin之心路历程

Kotlin之心路历程 以小白眼光看kotlin kotlin这个小丫鬟被谷歌扶正为大房两年,期间看过不少博文,很多人也已经把个人项目迁移到kotlin了,当然国外的开发者更给力,直接大部企业开发已经kotlin,也订阅了涛哥的极客时间(一直没时间看,果然看视频太费事,还是文章可以抽得时间挤一挤学),一直是不想学习啊,一个人的惰性就是这样,java又不是不能用,代码通俗易懂。说句心里话,jav...

ApkCore的专栏 497

Kotlin 进阶之路 开篇

写在前面 Kotlin 从出现以来,一直在不断的优化,发展可以说是非常的迅速,以前断断续续的学习了一下,说来惭愧一直没能坚持学习下去。 今年 Google 已经将 Kotlin 作为 Android 开发的官方支持语言,现在上车还不晚,赶紧动起来。经常看到一些大佬分享的 Kotlin 项目,苦于看不懂又一直没逼着自己去学习。从现在开始,我要正式进军 Kotlin 了,特在此记录一下学习历程,一方面...

cczhengv 554
上一篇: Opt-in requirement marker annotation on override requires the same marker on base declaration.
下一篇: Kotlin学习历程——继承
hepingdev
博客等级 码龄5年 3581粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hepingdev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值