Kotlin基本语法-类与集成

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

类

使用class 关键字定义:

class Invoice{
}
类的定义由以下几部分组成: 类名, 类头部(指定类的类型参数, 主构造器, 等等.), 以及由大括号括起的类主体部分. 类的头部和主体部分都是可选的; 如果类没有主体部分, 那么大括号也可以省略.

class Invoive

构造器
Kotlin 中的类可以有一个主构造器 (primary constructor), 以及一个或多个次构造器 (secondary constructor). 主构造器是类头部的一部分, 位于类名称(以及可选的类型参数)之后.

class Person constructor(firstName: String) {
}
如果主构造器没有任何注解(annotation), 也没有任何可见度修饰符, 那么 constructor 关键字可以省略:

class Person(firstName: String) {
}
主构造器中不能包含任何代码. 初始化代码可以放在 初始化代码段 (initializer block) 中, 初始化代码段使用init 关键字作为前缀:

class Customer(name: String) {
    init {
        logger.info("Customer initialized with value ${name}")
    }
}
注意, 主构造器的参数可以在初始化代码段中使用. 也可以在类主体定义的属性初始化代码中使用:

class Customer(name: String) {
    val customerKey = name.toUpperCase()
}
实际上, Kotlin 有一种简洁语法, 可以通过主构造器来定义属性并初始化属性值:

class Person(val firstName: String, val lastName: String, var age: Int) {
  // ...
}

与通常的属性一样, 主构造器中定义的属性可以是可变的(var), 也可以是只读的(val).

如果构造器有注解, 或者有可见度修饰符, 这时 constructor关键字是必须的, 注解和修饰符要放在它之前:

class Customer public @Inject constructor(name: String) { ... }
次级构造器(secondary constructor)
类还可以声明 次级构造器 (secondary constructor), 使用 constructor 关键字作为前缀

class Person {
    constructor(parent: Person) {
        parent.children.add(this)
    }
}
如果类有主构造器, 那么每个次级构造器都必须委托给主构造器, 要么直接委托, 要么通过其他次级构造器间接委托. 委托到同一个类的另一个构造器时, 使用this 关键字实现:

class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}
如果一个非抽象类没有声明任何主构造器和次级构造器, 它将带有一个自动生成的, 无参数的主构造器. 这个构造器的可见度为 public. 如果不希望你的类带有 public 的构造器, 你需要声明一个空的构造器, 并明确设置其可见度:

class DontCreateMe private constructor () {
}
注意: 在 JVM 中, 如果主构造器的所有参数都指定了默认值, 编译器将会产生一个额外的无参数构造器, 这个无参数构造器会使用默认参数值来调用既有的构造器. 有些库(比如 Jackson 或 JPA) 会使用无参数构造器来创建对象实例, 这个特性将使得 Kotlin 比较容易与这种库协同工作.
class Customer(val customerName: String = "")
创建类的实例
要创建一个类的实例, 我们需要调用类的构造器, 调用方式与使用通常的函数一样:
val invoice = Invoice()
val customer = Customer("Joe Smith")
注意, Kotlin 没有 new 关键字.

类成员
类中可以包含以下内容:
  • 构造器和初始化代码块
  • 函数
  • 属性
  • 嵌套类和内部类
  • 对象声明
继承

Kotlin 中所有的类都有一个共同的超类 Any, 如果类声明时没有指定超类, 则默认为 Any:

class Example // 隐含地继承自 Any

Any 不是 java.lang.Object; 尤其要注意, 除 equals(), hashCode() 和 toString() 之外, 它没有任何成员. 详情请参见 与 Java 的互操作性.

要明确声明类的超类, 我们在类的头部添加一个冒号, 冒号之后指定超类:
open class Base(p: Int)

class Derived(p: Int) : Base(p)
如果类有主构造器, 那么可以(而且必须)在主构造器中使用主构造器的参数来初始化基类.

如果类没有主构造器, 那么所有的次级构造器都必须使用 super 关键字来初始化基类, 或者委托到另一个构造器, 由被委托的构造器来初始化基类. 注意, 这种情况下, 不同的次级构造器可以调用基类中不同的构造器:
class MyView : View {
    constructor(ctx: Context) : super(ctx) {
    }


    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
    }
}
类上的 open 注解(annotation) 与 Java 的 final 正好相反: 这个注解表示允许从这个类继承出其他子类. 默认情况下, Kotlin 中所有的类都是 final 的, 这种设计符合 Effective Java, 一书中的第 17 条原则: 允许继承的地方, 应该明确设计, 并通过文档注明, 否则应该禁止继承.

成员的覆盖

我们在前面提到过, 我们很注意让 Kotlin 中的一切都明白无误. 而且与 Java 不同, Kotlin 要求明确地注解来标识允许被子类覆盖的成员(我们称之为 open), 而且也要求明确地注解来标识对超类成员的覆盖:
open class Base {
  open fun v() {}
  fun nv() {}
}
class Derived() : Base() {
  override fun v() {}
}

对于 Derived.v() 必须添加 override 注解. 如果遗漏了这个注解, 编译器将会报告错误. 如果一个函数没有标注 open 注解, 比如上例中的 Base.nv(), 那么在子类中声明一个同名同参的方法将是非法的, 无论是否添加 override 注解, 都不可以. 在一个 final 类(比如, 一个没有添加 open 注解的类)中, 声明 open 成员是禁止的.

当一个子类成员标记了 override 注解来覆盖父类成员时, 覆盖后的子类成员本身也将是 open 的, 也就是说, 子类成员可以被自己的子类再次覆盖. 如果你希望禁止这种再次覆盖, 可以使用 final 关键字:
open class AnotherDerived() : Base() {
  final override fun v() {}
}
属性的覆盖方式与方法覆盖类似. 注意, 你可以在主构造器的属性声明中使用 override 关键字:
open class Foo {
    open val x: Int get { ... }
}


class Bar1(override val x: Int) : Foo() {

}

你也可以使用一个 var 属性覆盖一个 val 属性, 但不可以反过来使用一个 val 属性覆盖一个 var 属性.允许这种覆盖的原因是, val 属性本质上只是定义了一个 get 方法, 使用 var 属性来覆盖它, 只是向后代类中添加了一个 set 方法.

如何才能 hack 我用到的那些类库呢?!

你可能曾经习惯于从类库中的某个类继承一个子类, 然后覆盖掉类库设计者并不期望你覆盖的某些方法, 以这种比较肮脏的手段来 hack 类库. 但在 Kotlin 中, 类与成员默认都是 final 的, 我们针对继承和覆盖问题所选择的这种设计原则, 将会带来一个问题, 就是前面所说的那种类库 hack 方式将会变得比较困难.

但我们认为这并不是一个缺点, 理由如下:
  • 程序设计的最佳实践原则认为, 你本来就不应该使用这种 hack 手段
  • 其他语言(比如 C++, C#)也使用了类似的原则, 大家使用起来并未遇到问题
  • 如果有人确实希望 hack, 仍然存在其他方法: 你可以用 Java 来编写你的 hack 代码, 然后通过 Kotlin 来调用(参见 与 Java 的互操作性). 另外 Aspect 框架就是为这类目的设计的, 你可以使用 Aspect 框架来解决这类问题.

覆盖的规则

在 Kotlin 中, 类继承中的方法实现问题, 遵守以下规则: 如果一个类从它的直接超类中继承了同一个成员的多个实现, 那么这个子类必须覆盖这个成员, 并提供一个自己的实现(可以使用继承得到的多个实现中的某一个). 为了表示使用的方法是从哪个超类继承得到的, 我们使用 super 关键字, 将超类名称放在尖括号类, 比如, super<Base>:
open class A {
  open fun f() { print("A") }
  fun a() { print("a") }
}

interface B {
  fun f() { print("B") } // 接口的成员默认是 'open' 的
  fun b() { print("b") }
}

class C() : A(), B {
  // 编译器要求 f() 方法必须覆盖:
  override fun f() {
    super<A>.f() // 调用 A.f()
    super<B>.f() // 调用 B.f()
  }
}
同时继承 A 和 B 是合法的, 而且函数 a() 和 b() 的继承也不存在问题, 因为对于这两个函数, C 类都只继承得到了唯一的一个实现. 但对函数 f() 的继承就发生了问题, 因为 C 类从超类中继承得到了两个实现, 因此在 C 类中我们必须覆盖函数 f(), 并提供我们自己的实现, 这样才能消除歧义.

抽象类

类本身, 或类中的部分成员, 都可以声明为 abstract 的. 抽象成员在类中不存在具体的实现. 注意, 我们不必对抽象类或抽象成员标注 open 注解 – 因为它显然必须是 open 的.

我们可以使用抽象成员来覆盖一个非抽象的 open 成员:
open class Base {
  open fun f() {}
}


abstract class Derived : Base() {
  override abstract fun f()
}
同伴对象(Companion Object)

与 Java 或 C# 不同, Kotlin 的类没有静态方法(static method). 大多数情况下, 建议使用包级函数(package-level function)替代静态方法.

如果你需要写一个函数, 希望使用者不必通过类的实例来调用它, 但又需要访问类的内部信息(比如, 一个工厂方法), 你可以将这个函数写为这个类之内的一个对象声明 的成员, 而不是类本身的成员.

具体来说, 如果你在类中声明一个 同伴对象, 那么只需要使用类名作为限定符就可以调用同伴对象的成员了, 语法与 Java/C# 中调用类的静态方法一样.

封闭类(Sealed Class)

封闭类(Sealed class)用来表示对类阶层的限制, 可以限定一个值只允许是某些指定的类型之一, 而不允许是其他类型. 感觉上, 封闭类是枚举类(enum class)的一种扩展: 枚举类的值也是有限的, 但每一个枚举值常数都只存在唯一的一个实例, 封闭类则不同, 它允许的子类类型是有限的, 但子类可以有多个实例, 每个实例都可以包含它自己的状态数据.


要声明一个封闭类, 需要将 sealed 修饰符放在类名之前. 封闭类可以有子类, 但所有的子类声明都必须嵌套在封闭类的声明部分之内.
sealed class Expr {
    class Const(val number: Double) : Expr()
    class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
}
注意, 从封闭类的子类再继承的子类(间接继承者)可以放在任何地方, 不必在封闭类的声明部分之内.

使用封闭类的主要好处在于, 当使用 when expression 时, 可以验证分支语句覆盖了所有的可能情况, 因此就不必通过 else 分支来处理例外情况.

fun eval(expr: Expr): Double = when(expr) {
    is Expr.Const -> expr.number
    is Expr.Sum -> eval(expr.e1) + eval(expr.e2)
    Expr.NotANumber -> Double.NaN
    // 不需要 `else` 分支, 因为我们已经覆盖了所有的可能情况
}

【Kotlin】Kotlin 基础语法指南 kotlin复制代码。 阅读详情

相关推荐

Kotlin语法整理

Kotlin语法整理

riven78的博客 1190

Kotlin的基本使用和基类封装、MVVM和DataBinding

犹豫要不要写这篇关于Kotlin的文章很久了,网上大把大把的Kotlin的项目和各种知识点与代码,到目前为止已经半年多没接触Kotlin项目了,重新捡起来,就当是熟悉一下基本写法吧,以文章的形式去整理并加深一下印象,同时可以帮助一下正在初学Kotlin的同学。 这篇文章你可以了解到 1.Kotlin基本使用 2.Kotlin项目基类搭建封装 3.MVVM框架实战使用 4.DataBinding数据绑定实战 首先讲一下MVVM是很有必要的,因为一开始我接触到Kotlin就是与MVVM配合使用的,如果你和我说用

As_thin的博客 4281

Kotlin编程基础教程:Kotlin与Java互操作

作者:禅与计算机程序设计艺术 1.背景介绍 Kotlin是一种多平台语言,兼容Java。从语法上来说,它与Java基本一致,但为了更好的学习体验、功能实现、更简洁的代码风格等,也针对多平台特性做了一些优化。在实际应用中,通过Kotlin可以有效地减少重复的代码量并提高开发效率。因此,本文的主要目标就

AI天才研究院 326

Kotlin 类基础

kotlin是OOP模式的语言,其中的类是对事物的特征、逻辑的综合抽象,用关键词class声明一个类。包含class name, class header, class body。 class A {} class Empty 类的基本结构:构造函数,属性,方法 构造函数 构造函数是实例化一个类时调用的api,它可以接收参数来控制对象的特征与逻辑 构造函数可以用关键词constructor声明 kotlin的类有两种构造函数,主构造函数、次构造函数 主构造函数是class header的一部

ljjliujunjie123的博客 4406

工业质检实战:如何用MVTec AD数据集训练你的第一个无监督异常检测模型

本文提供了一份基于MVTec AD数据集的工业质检实战指南,详细介绍了如何从零开始训练一个无监督异常检测模型。内容涵盖数据预处理、模型架构选型(如CAE、GAN与特征字典方法)、特征提取、损失函数设计以及关键的阈值确定与后处理流程,旨在帮助工程师快速掌握将AI技术落地于实际产线质检的核心步骤与调参经验。

weixin_29182481的博客 459

告别手动输入!用Burp插件+ddddocr,5分钟搞定图片验证码自动识别

本文详细介绍了如何利用Burp插件和ddddocr开源库快速构建图片验证码自动识别系统,实现高效、零成本的验证码自动化解决方案。通过环境搭建、性能调优和Burp Suite深度集成,显著提升安全测试效率,特别适用于金融和电商系统的批量测试场景。

weixin_29099217的博客 202

Kotlin学习之 8继承

Kotlin 继承一.Kotlin 中所有类都继承该 Any 类,它是所有类的超类,对于没有超类型声明的类是默认超类: class Example // 从 Any 隐式继承 Any 默认提供了三个函数:equals()hashCode()toString() Kotlin中没有Object这个类。Any是不是和Java中的Object是非常相似的。并且Object也是只提供上面三个方法。 注意:

wenzhi的博客 381

计组头哥实验 实验三 MIPS寄存器实验

了解 MIPS 寄存器文件基本概念,进一步熟悉多路选择器、译码器、解复用器等 Logisim 组件的使用,并利用相关组件构建 MIPS 寄存器文件。

gdz0007的博客 1万+

Kotlin基础(七):数据类和封闭类

本文主要讲解kotlin数据类(DataClass)和封闭类(SealedClasses),包括使用数据类,对象复制,数据类成员的解构,使用封闭类,以及数据类和封闭类在Android开发中的应用。

分享计算机基础,android,C/C++,音视频等内容 1322

大疆mini 3 pro rtmp推流(带屏遥控器不支持)windows

大疆mini 3 pro无人机rtmp推流(带屏遥控器不支持)至windows电脑

xbsigeibwkouvfcj的博客 3430

ESP32-CAM+STM32实战:5步搞定无线图像传输到TFT屏(附完整代码)

本文详细介绍了如何利用ESP32-CAM和STM32实现无线图像传输到TFT屏幕的完整方案。通过5个关键步骤,包括硬件连接、ESP32-CAM配置、STM32数据接收、TFT屏幕驱动及系统优化,开发者可以快速构建高效的图像传输系统。特别介绍了RGB565格式的处理技巧,并提供了完整的代码实现,适用于智能家居、工业监控等多种应用场景。

weixin_30316097的博客 484

kotlin 入门语法

Kotlin 是一种现代化的静态类型编程语言,它是一种基于 JVM 的语言,可以与 Java 无缝地集成。

XIAOTONGZHU的博客 454

利用ArcGIS快速生成等高线边界,完成地形图拼图

地形图边界一般在CAD中手动绘制,然而,一幅边缘复杂的地形图边界的绘制需要花费大量时间和精力,为了减少重复性工作,提高效率,用ArcGIS软件可以自动生成实测地形图的边界

yl14774636230的博客 9068

Android的swift语言Kotlin中文开发文档

转自GitHub https://github.com/huanglizhuo/kotlin-in-chinese?utm_source=tuicool&utm_medium=referral 2016.3.4  gitbook 墙内访问速度很糟糕 现在有了 墙内地址 啦 :)  国内服务器由 掘金 赞助  稀土掘金:挖掘最优质的互联网技术 / 联合编辑每日精选内容 / 移

疾风的博客 463

STM32实现简单的智能电梯控制

上述代码实现了一个简单的智能电梯控制器。电梯的状态包括IDLE(停止)、UP(向上移动)和DOWN(向下移动)三种状态。通过向上和向下按钮的按下,可以控制电梯移动到指定的楼层。在主循环中,不断读取当前楼层的按钮状态,并根据电梯状态决定执行的动作。具体的楼层数量和按钮的GPIO引脚可以根据实际情况进行调整。要实现简单的智能电梯控制,我们可以使用STM32微控制器来实现。

2401_85258012的博客 336

基于Playwright与异步技术的公司评价智能爬取实战:以Glassdoor为例

本文将介绍一套基于最新Python技术的智能爬虫解决方案,使用Playwright实现浏览器自动化,结合异步编程和智能解析技术,高效抓取Glassdoor等平台的公司评价数据。我们不仅关注数据获取,更注重数据的结构化处理和反反爬虫策略的实现。

2201_76125261的博客 223

Kotlin基本语法

Kotlin基本语法

weixin_45625639的博客 1385

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

kotlin基本语法

函数 表达式:fun 方法名(参数名1: 数据类型, 参数名2: 数据类型): 返回值数据类型{ } 普通用法 fun test(a: Int): String { return ""; } // 将表达式作为函数体,花括号可以省略 fun test1(a: Int): Int = 1; // 函数返回无意义的值Unit,返回值可省略 fun printSum(a: Int, b: Int) { println("sum of $a and $b is ${a + b}") }

Florizt 5999

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Kotlin属性和字段与基本语法

Kotlin 属性 字段 基本语法

永远不要停下学习的脚步。 5166

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

kotlin基本篇:kotlin与java语法不同写法比较

写在前面 最近谷歌大会强调Kotlin将在今后广泛拓展应用,毕竟相比java优势凸显,所以学习 Kotlin 已经成为我们必经之路。本想着等到某一天大佬们把坑踩得差不多了,又或者我们开发中要用到了,再学也不迟,毕竟我们还是要优先把时间和精力留给实际开发中需要学习的知识上,而现在呢也只能跟着冲锋陷阵了不然就落后了。 对象 Java 的写法 MainActivity.th...

P876643136的博客 1679

Kotlin基础语法

Kotlin是一种在Java虚拟机上运行的静态类型编程语言,被称为之为Android世界的Swift,Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行。在Google I/O 2017中,Google 宣布 Kotlin 成为 Android 官方开发语言,足见Kotlin将来会成为android开发的主流语言。

qtiao的博客 1万+

快速入门Kotlin语言(基本语法概要)

引言 基本数据类型 常量和变量 函数 字符串模板 条件表达式 非null检测 类 区间 集合 摘要

王玉见的博客 3800

Android:关于Kotlin的入门语法指南(类、变量 & 函数)都总结在这里了!

今天,carson将主要详细讲解Kotlin的所有基本语法

Carson带你学Android 2687

第十四章 Kotlin入门语法(类、变量 & 函数)

这是一份全面 & 详细的kotlin入门语法指南(类、变量 & 函数)

Stay Hungry Stay Foolish 求知若饥 虚心若愚 1025
上一篇: 获取上个月的最后一天的方法
下一篇: Kotlin基础语法-属性(Property)与域(Field)
keepuping
博客等级 码龄11年 2粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值