Kotlin允许我们为自己的类型提供预定义的一组操作符的实现。这些操作符具有固定的符号表示(如 + 或 *) 和固定的优先级。为实现这样的操作符,我们为相应的类型(即二元操作符左侧的类型和一元操作符的参数类 型)提供了一个固定名字的成员函数或扩展函数。重载操作符的函数需要用 operator 修饰符标记。

  另外,我们描述为不同操作符规范操作符重载的约定。

一元操作

  一元前缀操作符

表达式 翻译为
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()

  这个表是说,当编译器处理例如表达式 +a 时,它执行以下步骤

    — 确定 a 的类型,令其为 T;

    — 为接收者 T 查找一个带有 operator 修饰符的无参函数 unaryPlus(),即成员函数或扩展函数;

    — 如果函数不存在或不明确,则导致编译错误;

    — 如果函数存在且其返回类型为 R,那就表达式 +a 具有类型 R;

  注意 这些操作以及所有其他操作都针对基本类型做了优化,不会为它们引入函数调用的开销。

  以下是如何重载一元减运算符的示例

data class Point(val x: Int, val y: Int)

operator fun Point.unaryMinus() = Point(-x, -y) 

val point = Point(10, 20)

fun main() {
println(-point) // 输出“Point(x=-10, y=-20)”
}

  

递增与递减

表达式 翻译为
a++ a.inc()
a-- a.dec()

  inc() 和 dec() 函数必须返回一个值,它用于赋值给使用 ++ 或 -- 操作的变量。它们不应该改变在其上 调用 inc() 或 dec() 的对象

  编译器执行以下步骤来解析后缀形式的操作符,例如 a++

    — 确定 a 的类型,令其为 T

    — 查找一个适用于类型为 T 的接收者的、带有 operator 修饰符的无参数函数 inc()

    — 检测函数的返回类型是 T 的子类型。

  计算表达式的步骤是

    — 把 a 的初始值存储到临时存储 a0 中

    — 把 a0.inc() 结果赋值给 a

    — 把 a0 作为表达式的结果返回。

  对于 a--,步骤是完全类似的。

  对于前缀形式 ++a 和 --a 以相同方式解析,其步骤是:

    — 把 a.inc() 结果赋值给 a 

    — 把 a 的新值作为表达式结果返回

二元操作

算术运算符

表达式 翻译为
a+b a.plus(b)
a-b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b) 、a.mod(b) (已弃用)
a..b a.rangeTo(b)

  对于此表中的操作,编译器只是解析成翻译为列中的表达式。

  请注意,自 Kotlin 1.1 起支持 rem 运算符。Kotlin 1.0 使用 mod 运算符,它在 Kotlin 1.1 中被弃用

示例:下面是一个从给定值起始的 Counter 类的示例,它可以使用重载的 + 运算符来增加计数

data class Counter(val dayIndex: Int) {
operator fun plus(increment: Int): Counter {
return Counter(dayIndex + increment) }
}

“In”操作符

表达式 翻译为
a in b b.contains(a)
a !in b !b.contains(a)

  对于 in 和 !in,过程是相同的,但是参数的顺序是相反的

索引访问操作符

表达式 翻译为
a[i] a.get(i)
a[i,j] a.get(i,j)
a[i_1,......,i_n] a.get(i_1,......,i_n)
a[i] = b a.set(i,b)
a[i,j] = b a.set(i,j,b)
a[i_1 , ...... ,i_n] = b a.set(i_1, ...... , i_n , b)

  

  方括号转换为调用带有适当数量参数的 get 和 set

调用操作符

表达式 翻译为
a() a.invoke()
a(i) a.invoke(i)
a(i , j) a.invoke(i , j)
a(i_1 , ..... , i_n) a.invoke(i_1,.......,i_n)

  圆括号转换为调用带有适当数量参数的 invoke

广义赋值

表达式 翻译为
a += b a.plusAssign(b)
a -= b a.minusAssign(b)
a *= b a.timesAssign(b)
a /= b a.divAssign(b)
a %= b a.remAssign(b) , a.modAssign(b)(已弃用)

  对于赋值操作,例如 a += b,编译器执行以下步骤:

    — 如果右列的函数可用

    — 如果相应的二元函数(即 plusAssign() 对应于 plus())也可用,那么报告错误(模糊),

    — 确保其返回类型是 Unit,否则报告错误,

    — 生成 a.plusAssign(b) 的代码;

    — 否则试着生成 a = a + b 的代码(这里包含类型检测:a + b 的类型必须是 a 的子类型)。

  注意:赋值在 Kotlin 中不是表达式

相等与不等操作符

表达式 翻译为
a == b a?.equals(b) ?: (b === null)
a != b !(a?.equals(b) ? : (b===null))

  这些操作符只使用函数 equals(other: Any?): Boolean,可以覆盖它来提供自定义的相等性检测实现。 不会调用任何其他同名函数(如 equals(other: Foo))。

  注意:=== 和 !==(同一性检测)不可重载,因此不存在对他们的约定。

  这个 == 操作符有些特殊:它被翻译成一个复杂的表达式,用于筛选 null 值。null == null 总是 true,

  对于非空的 x ,x == null 总是 false 而不会调用 x.equals()

比较操作符

表达式 翻译为
a > b a.compareTo(b) > 0
a < b a.compareTo(b) < 0
a >= b a.compareTo(b) >= 0
a <= b a.compareTo(b) <= 0

  所有的比较都转换为对 compareTo 的调用,这个函数需要返回 Int 值

属性委托操作符

  provideDelegate 、getValue 以及 setValue 操作符函数已在委托属性中描述

具名函数的中缀调用

  我们可以通过中缀函数的调用 来模拟自定义中缀操作符

例:

infix fun Person.text(s:Student):Person = Person().plus(s)

  

kotlin更多语言结构——>操作符重载的更多相关文章

  1. lua 14 metatable (类似操作符重载)

    转自:http://www.runoob.com/lua/lua-metatables.html 感性认识: “Lua中Metatable这个概念, 国内将他翻译为元表. 元表为重定义Lua中任意一个 ...

  2. Kotlin操作符重载:把标准操作加入到任何类中(KAD 17)

    作者:Antonio Leiva 时间:Mar 21, 2017 原文链接:https://antonioleiva.com/operator-overload-kotlin/ 就像其他每种语言一样, ...

  3. Kotlin——最详细的操作符与操作符重载详解(上)

    本篇文章为大家详细的介绍Koltin特有的操作符重载.或许对于有编程经验的朋友来说,操作符这个词绝对不陌生,就算没有任何编辑基础的朋友,数学中的算数运算符也绝不陌生.例如(+.-.*./.>.& ...

  4. Kotlin 之操作符重载

    Kotlin 之操作符重载   参考: kotlin in action kotlin 官方参考文档 运算符重载 Kotlin允许我们为自己的类型提供预定义的一组操作符实现(这些操作符都对应的成员函数 ...

  5. kotlin之操作符重载

    一元操作符 表达式 对应的函数 +a a.unaryPlus() -a a.unaryMinus() !a a.not() a++ a.inc() a-- a.dec() fun main(arg: ...

  6. KOTLIN开发语言文档(官方文档) -- 2.基本概念

    网页链接:https://kotlinlang.org/docs/reference/basic-types.html 2.   基本概念 2.1.  基本类型 从可以在任何变量处理调用成员函数和属性 ...

  7. Java 语言结构【转】

    Java 语言结构 基础:包(Package).类(Class)和对象(Object) 了解 Java 的包(Package).类(Class)和对象(Object)这些基础术语是非常重要的,这部分内 ...

  8. 06. Go 语言结构体

    Go语言结构体(struct) Go 语言通过用自定义的方式形成新的类型,结构体是类型中带有成员的复合类型.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. Go 语言中的类 ...

  9. Kotlin开发语言文档(官方文档)-- 目录

    开始阅读Kotlin官方文档.先上文档目录.有些内容还未阅读,有些目录标目翻译还需琢磨琢磨.后续再将具体内容的链接逐步加上. 文档链接:https://kotlinlang.org/docs/kotl ...

  10. php入门 数据类型 运算符 语言结构语句 函数 类与面向对象

    php PHP-enabled web pages are treated just like regular HTML pages and you can create and edit them ...

随机推荐

  1. 【Java】JDBC Part4 Transaction 事务

    JDBC Part4 Transaction 事务 什么是事务? 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消. 也就是原子性,一个事务中的一系列的 ...

  2. 【Uni-App】底部栏踩坑

    一.Page.json一定要注册这个页面 Uni-App通过page.json找到,解析不到这个页面文件是没用的 二.配置tabBar属性 "tabBar":{ "col ...

  3. 【PowerDesigner】快速上手

    破解下载地址: https://www.onlinedown.net/soft/577763.htm 安装点试用,完成安装后把破解的dll库文件替换即可 学习参考自: https://www.bili ...

  4. 【Layui】08 时间线 Timeline

    文档地址: https://www.layui.com/demo/timeline.html 常规时间线: <ul class="layui-timeline"> &l ...

  5. Deepin20系统开机报错——You are in emergency mode ... Cannot open access to console, the root account is locked. emergency mode/“journalctl -xb”

    参考: https://knowledge.ipason.com/ipKnowledge/knowledgedetail.html/1286 https://blog.csdn.net/wenfei1 ...

  6. WhaleScheduler为银行业全信创环境打造统一调度管理平台解决方案

    项目背景 数字金融是数字经济的重要支撑和驱动力.近年来,我国针对数字金融的发展政策频频出台,<金融科技发展规划 (2022-2025年)>.<"十四五"数字经济发 ...

  7. CF1051F题解

    The Shortest Statement 算法:树链剖分,最小生成树,最短路. 先讲一下题意:有一个 \(n\) 点 \(m\) 边的无向连通图,\(q\) 次询问,每次询问 \(a\) 到 \( ...

  8. WPF 设备输入事件封装

    本文主要介绍WPF应用对鼠标输入.触摸屏触笔以及触摸事件的封装 之前有简单说明设备输入类型 WPF 屏幕点击的设备类型 - 唐宋元明清2188 - 博客园 (cnblogs.com) 1.鼠标 - 通 ...

  9. 关于对 Tomcat 进行小版本升级的快速解决方案

    1.背景描述 原来的 Tomcat 在部署时,使用的是最新的版本 9.0.40 . 经过一段时间后,在原来的 Tomcat 版本中,发现存在漏洞. 因此,需要将旧版本(9.0.40)升级到没有漏洞的新 ...

  10. check Str's Character appearence frequence is ge 1

    import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ; import java.util.*; public class HackerRa ...