1. 程式人生 > >Kotlin 其他(七) --- 操作符過載(Operator overloading)

Kotlin 其他(七) --- 操作符過載(Operator overloading)

1、操作符過載

Kotlin 允許我們為自己的型別提供預定義的一組操作符的實現。這些操作符具有固定的符號表示 (如 +*)和固定的優先順序。為實現這樣的操作符,我們為相應的型別(即二元操作符左側的型別和一元操作符的引數型別)提供了一個固定名字的 成員函式或擴充套件函式。
過載操作符的函式需要用 operator 修飾符標記。

另外,我們描述為不同操作符規範操作符過載的約定。

2、一 元操作

2.1 一元字首操作符

表示式 翻譯為
+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) println(-point) // 輸出“(-10, -20)”

2.2 遞增與遞減

表示式 翻譯為
a++ a.inc() + 見下文
a– a.dec() + 見下文
!a a.not()

inc()dec() 函式必須返回一個值,它用於賦值給使用 ++-- 操作的變數。它們不應該改變在其上呼叫 inc()dec() 的物件。

編譯器執行以下步驟來解析字尾形式的操作符,例如 a++:

  • 確定 a 的型別,令其為 T
  • 查詢一個適用於型別為 T 的接收者的、帶有 operator
    修飾符的無引數函式 inc()
  • 檢查函式的返回型別是 T 的子型別。

計算表示式的步驟是:

  • a 的初始值儲存到臨時儲存 a0 中;
  • 把 a.inc() 結果賦值給 a;
  • 把 a0 作為表示式的結果返回。

對於 a–,步驟是完全類似的。

對於字首形式 ++a 和 –a 以相同方式解析,其步驟是:

  • 把 a.inc() 結果賦值給 a;
  • 把 a 的新值作為表示式結果返回。

3、二元操作

3.1 算術運算子

表示式 翻譯為
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)
    }
}

3.2 “In”操作符

表示式 翻譯為
a in b b.contains(a)
a !in b !b.contains(a)

對於 in 和 !in,過程是相同的,但是引數的順序是相反的。

3.3 索引訪問操作符

表示式 翻譯為
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。

3.4 呼叫操作符

表示式 翻譯為
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。

3.5 廣義賦值

表示式 翻譯為
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 中不是表示式。

3.6 相等與不等操作符

表示式 翻譯為
a == b a?.equals(b) ?: (b === null)
a != b !(a?.equals(b) ?: (b === null))

注意:===!==(同一性檢查)不可過載,因此不存在對他們的約定。

這個 == 操作符有些特殊:它被翻譯成一個複雜的表示式,用於篩選 null 值。 null == null 總是 true,對於非空的 xx == null 總是 false 而不會呼叫 x.equals()

3.7 比較操作符

表示式 翻譯為
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 值

3.8 屬性委託操作符

provideDelegate、 getValue 以及 setValue 操作符函式已在 委託屬性 中描述。

4、 命名函式的中綴呼叫

我們可以通過中綴函式的呼叫 來模擬自定義中綴操作符。

相關推薦

Kotlin 其他 --- 操作符過載Operator overloading

1、操作符過載 Kotlin 允許我們為自己的型別提供預定義的一組操作符的實現。這些操作符具有固定的符號表示 (如 + 或 *)和固定的優先順序。為實現這樣的操作符,我們為相應的型別(即二元操作符左側的型別和一元操作符的引數型別)提供了一個固定名字的 成員函式

C++學習筆記--操作符過載 友元函式 類的繼承 訪問控釋protected

C++ Primer Plus的閱讀大概到這邊也就先暫時告一段落了(因為開學了!!) 然後近期找來了C++ Primer稍微翻了翻覺得確實寫得比Plus要好一些,而且加入了C++11的新特性,但是無論哪本書對於這些最基本的功能應用大抵也是差不多的,所以也沒覺得看的是Plu

類和物件17—— 操作符過載

1、操作符過載的基本語法   所謂過載,就是重新賦予新的含義。函式過載就是對一個已有的函式賦予新的含義,使之實現新功能,因此,一個函式名就可以用來代表不同功能的函式,也就是”一名多用”。   運算子也可以過載。實際上,我們已經在不知不覺之中使用了運算子過載。例如,大家都已習慣於用加法運算子”+”對整數、單

c++實現日期類(class Date) 建構函式 拷貝構造 操作符過載輸入輸出 比較操作 算數運算 自增自減

註釋比較詳細,可以直接跑起來,直接上程式碼(vs2012 win7) 一、標頭檔案 /************** Date.h ***************/ #pragma once #include <iostream> using name

C++ 操作符過載小結 持續更新ing (歡迎收藏)

操作符過載一個原則是:被操作的資料型別中 至少有一個是自定義的型別(使用class定義類),如果被操作的變數都是基本型別,那麼就不能定義操作符過載。 如果過載了new,則必須過載delete,因為系統知道了你自定義了怎麼new一個空間, 但是呢,你使用delete的時候,系統並

C++操作符過載總結operator小結 更新ing

#include <iostream> #include<string.h> #include<stdlib.h> using namespace std; /*操作符過載一個原則是:被操作的資料型別,至少有一個是自定義的型別, * 如果被操作的變數都是基本型別,那麼

操作符過載

目錄 1. 結論 2. 邏輯操作符過載 3. 逗號操作符過載 1. 結論 前面兩次筆記都是C++中可以過載且無副作用的操作符,本次筆記比較特殊,主要列出兩個C++語法允許過載、但在工程中不應該(

第一次項目上Linux服務器:——Tomcat+ngnix+域名的簡單配置

src 簡單 一次 str b2b 準備工作 分享圖片 TP 服務器 1、準備工作   安裝好jdk+tomcat+nginx相關配置,請參考歷史博客 2、修改Nginx配置文件   修改配置文件如下: 3、修改Tomcat配置文件   修改配置文件如下:

java 重寫override過載overload 的實現原理

    剛開始學習Java的時候,就瞭解了Java這個比較有意思的特性:重寫 和 過載。開始的有時候從名字上還總是容易弄混。我相信熟悉Java這門語言的同學都應該瞭解這兩個特性,可能只是從語言層面上了解這種寫法,但是jvm是如何實現他們的呢,並不是很清楚。 過載官方給出的介

Hadoop學習記錄、MapReduce檔案分解與合成

1.將若干個小檔案打包成順序檔案 public class SmallFilesToSequenceFileConverter extends Configured implements Tool { static class SequenceFileMapper

大資料系列之——hive、hive詳解及應用

目錄 2.HQL 一、HIVE概述 1.Hadoop分散式計算遇到的問題 MapReduce只能用java開發(也支援其他語言,但是不是主流)需要對Hadoop的底層原理 api比較瞭解才能順暢的開發出分散式的處

重寫override過載overload的區別

1 /// <summary> 2 /// 定能基類動物類 3 /// </summary> 4 /// <returns></returns> 5 public class Anima

重寫override過載overload的區別

1、重寫(override) 重寫,就是說在定義這個方法的類的父類中有一個與這個方法同名且引數型別列表都相同的方法,在子類中這個方法被重寫了。在對這個子類的例項呼叫該方法時,編輯器確切的知道呼

C++函式的隱藏遮蔽、覆蓋override,即重寫,多型的實現原理過載overload)

零、前言 (1)函式過載發生在同一個類或頂層函式中,同名的函式而具有不同的引數列表 (2)函式覆蓋(重寫)發生在繼承層次中,該函式在父類中必須是virtual,而子類的該函式必須與父類有相同的引數列表 (3)函式**隱藏(遮蔽)**發生在繼承層次中,父類和子類同

node.js學習、express框架建立api介面

根據官方文件,用如下方式構造請求: app.get("/login/:username/:password",function (req, res) { console.log(req); res.send("get it");

Java面試題——關於重寫override過載overload

一. 首先,什麼是重寫?什麼是過載? 1.重寫(override)   重寫是發生於父類與子類之間多型性的一種表現,簡單的說就是子類重寫父類的“可被重寫”的方法,為什麼說“可被重寫”呢,因為在Java中含有private、final以及static等修飾符的

快速學習Kotlin集合與操作符

集合是我們在程式碼編寫時常用的操作資料的方式之一,具有非常重要的作用。 在kotlin中也有集合的概念,kotlin中的集合一般有三種:List、Map以及Set三種。而這三種集合每種又可以分為可變集合與不可變集合兩種。 不可變集合 顧名思義,不可變集合就是集合在初始化

C#中如何利用操作符過載和轉換操作符 轉載

操作符過載 有的程式語言允許一個型別定義操作符應該如何操作型別的例項,比如string型別和int型別都過載了(==)和(+)等操作符,當編譯器發現兩個int型別的例項使用+操作符的時候,編譯器會生成把兩個整數加到一起的程式碼。當編譯器發現兩個string型別的例項使用+操作符的時候,編譯器會生成把兩個

Next.js踩坑入門系列 —— 其他相關知識

Next.js踩坑入門系列 (一) Hello Next.js (二) 新增Antd && CSS (三) 目錄重構&&再談路由 (四) Next.js中期填坑 (五) 引入狀態管理Redux (六) 再次重構目錄 (七) 其他相關知識 獲

lua 14 metatable 類似操作符過載

轉自:http://www.runoob.com/lua/lua-metatables.html   感性認識: “Lua中Metatable這個概念, 國內將他翻譯為元表. 元表為重定義Lua中任意一個物件(值)的預設行為提供了一種公開入口. 如同許多OO語言的操作符過載或方法過載. Met