前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Kotlin | 7.运算符重载及其他约定

Kotlin | 7.运算符重载及其他约定

作者头像
Jingbin
发布于 2021-03-02 07:56:14
发布于 2021-03-02 07:56:14
98000
代码可运行
举报
文章被收录于专栏:Android 技术栈Android 技术栈
运行总次数:0
代码可运行

本章内容包括:

  • 运算符重载
  • 约定:支持各种运算的特殊命名函数
  • 委托属性

7.1 运算符

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
          /**-------------------- 7.1.1 重载二元算术运算 ----------------------*/
        // 代码清单7.1 定义一个plus运算符
        data class Point(val x: Int, val y: Int) {
            // 定义一个名为 plus 的方法
            operator fun plus(other: Point): Point {
                return Point(x + other.x, y + other.y)
            }
        }
        println(Point(10, 10).plus(Point(12, 13)).x)// 22
        val point = Point(10, 10)
        val point2 = Point(12, 13)
        // 通过使用 + 号来调用plus方法
        println(point + point2)// Point(x=22, y=23)

        /*
        * 在使用了operator修饰符声明了plus函数后,你就可以直接使用_好来求和了。
        * 除了这个运算符声明为一个 成员函数 外,也可以把它定义为一个扩展函数
        */
        // 代码清单7.2 把运算符定义为扩展函数
        operator fun Point.plus(other: Point): Point {
            return Point(x + other.x, y + other.y)
        }

        /*
        * 可重载的二元算术运算符
        *  表达式     函数名
        *  a * b     times
        *  a / b     div
        *  a % b     mod
        *  a + b     plus
        *  a - b     minus
        */

        // 代码清单7.3 定义一个运算数类型不同的运算符
        operator fun Point.times(scale: Double): Point {
            return Point((x * scale).toInt(), (y * scale).toInt())
        }

        val point3 = Point(10, 20)
        println(point3 * 2.0)// Point(x=20,y=40)

        // 注意不能使用 2.0 * point3,如果需要使用需要另定义
        operator fun Double.times(point: Point): Point {
            return Point((this * point.x).toInt(), (this * point.y).toInt())
        }
        println(3.0 * point3)// Point(x=30,y=60)

        // 代码清单7.4 定义一个返回结果不同的运算符
        operator fun Char.times(count: Int): String {
            return toString().repeat(count)
        }
        println('a' * 3)// aaa

        /*
        * 没有用于位运算的特殊运算符
        * 以下,用于执行位运算的完整函数列表
        * shl  --  带符号左移
        * shr  --  带符号右移
        * ushr --  无符号右移
        * and  --  按位与
        * or   --  按位或
        * xor  --  按位异或
        * inv  --  按位取反
        */
        // 使用方法:
        println(0x0F and 0x0F)// 0
        println(0x0F or 0x0F)// 255
        println(0x1 shl 4)// 16

        /**-------------------- 7.1.2 重载复合赋值运算符 ----------------------*/
        // 对可变变量var有效,例子:
        var point1 = Point(1, 2)
        point1 += Point(1, 1)
        println(point1)// Point(x=2,y=3)

        // 将元素添加到可变集合,例子:
        val numbers = ArrayList<Int>()
        numbers += 42
        println(numbers[0])// 42

        /*
        * 如果你定义了一个返回值 Unit,名为plusAssign函数,Kotlin将会在用到+=运算符的地方调用它。
        * 其他如 minusAssign、timeAssign
        */
        operator fun <T> MutableCollection<T>.plusAssign(element: T) {
            this.add(element)
        }

        /*
        * a += b
        * a = a.plus(b)
        * a.plusAssign(b)
        * 运算符 += 可以被转换为plus或者plusAssign函数的调用
        * + 和 - 运算符总是返回一个新的集合。
        * +=和-=运算符用于可变集合时,始终就地修改它们,用于只读集合时,会返回一个修改过的副本。
        */
        val list = arrayListOf(1, 2)
        list += 3

        val newList = list + listOf(4, 5)
        println(list)// 就地修改 [1,2,3]
        println(newList)// 新的集合 [1,2,3,4,5]


        /**-------------------- 7.1.3 重载一元运算符 ----------------------*/
        // 代码清单7.5 定义一个一元运算符
        operator fun Point.unaryMinus(): Point {
            // 一元运算符无参数
            return Point(-x, -y)
        }

        val point4 = Point(10, 20)
        println(-point4)// Point(x=-10,y=-20)

        /*
        * +a  --   a.unaryPlus()
        * 一元运算符 + 被转换为unaryPlus函数的调用
        * 可重载的一元算法的运算符
        * 表达式   函数名
        * +a      unaryPlus
        * -a      unaryMinus
        * !a      not
        * ++a,a++ inc
        * --a,a-- dec
        */

        // 代码清单7.6 定义一个自增运算符
        operator fun BigDecimal.inc() = this + BigDecimal.ONE

        var db = BigDecimal.ZERO
        println(db++)// 0  在执行后添加
        println(++db)// 2  在执行前添加

7.2 重载比较运算符

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        /**-------------------- 7.2.1 等号运算符 equals ----------------------*/
        /*
        * == != 可以用于可空运算数
        * a == b  -> a? equals(b) ?: (b==null)
        */

        // 代码清单7.7 实现equals函数
        class Point(val x: Int, val y: Int) {

            // 重写在Any中定义的方法
            override fun equals(other: Any?): Boolean {
                // 优化:检查参数是否与this是统一对象
                if (other === this) return true
                // 检查参数类型
                if (other !is Point) return false
                // 智能转换为Point来访问x、y属性
                return other.x == x && other.y == y
            }
        }
        println(Point(10, 20) == Point(10, 20))// true
        println(Point(10, 20) != Point(5, 5))// true
        println(null == Point(10, 20))// false

        // 恒等运算符(===):来检查参数与调用equals的对象是否相同。
        // Any中的基本方法已经将equals方法标记为 operator 了


        /**-------------------- 7.2.2 排序运算符 compareTo ----------------------*/
        /*
        * a >= b  -> a.compareTo(b) >= 0
        * 两个对象的比较被转换为compareTo的函数调用,然后结果与零比较
        */

        // 代码清单7.8 实现 compareTo 方法
        class Person(val firstName: String, val lastName: String) : Comparable<Person> {

            override fun compareTo(other: Person): Int {
                // 按顺序调用给定的方法,并比较它们的值
                return compareValuesBy(this, other, Person::lastName, Person::firstName)
            }
        }

        val person = Person("Alice", "Smith")
        val person2 = Person("Bob", "Johnson")
        println(person < person2)// false

        /*
        * compareValuesBy 这个函数接收用来计算比较值的一系列回调,按顺序依次调用回调方法,两两一组分别做比较,
        * 并返回结果。如果值不同,则返回比较结果;如果它们相同,则继续调用下一个;如果没有更多的回调来调用,则返回0。
        * */
        println("abc" < "bac")// true

7.3 集合与区间的约定

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        /**-------------------- 7.3.1 通过下标来访问元素 get 和 set ----------------------*/
        // kotlin中可以使用类似java中数组中的方式来访问map中的元素---使用方括号
//        val value = map[key]
        // 也可以用同样的运算符来改变一个可变map的元素
//        mutableMap[key] = newValue

        // 使用方括号来引用点的坐标:p[0]访问x坐标,p[1]访问y坐标。
        // 代码清单7.9 实现 get 约定
        // 定义一个名为 get 的运算符函数
        operator fun Point.get(index: Int): Int {
            // 根据给出的index返回对应的坐标
            return when (index) {
                0 -> x
                1 -> y
                else -> throw IndexOutOfBoundsException("Invalid coordinate $index")
            }
        }

        val point = Point(1, 2)
        println(point[1])// 2

        /*
        * x[a,b] -> x.get(a,b)
        *
        * get的参数可以是任何类型,而不只是Int,还可以是多个参数。例如 matrix[row,rol]
        */
        // 代码清单7.10 实现 set 的约定方法
        data class MutablePoint(var x: Int, var y: Int)

        // 定义一个名为 set 的运算符函数
        operator fun MutablePoint.set(index: Int, value: Int) {
            when (index) {
                // 根据给出的index参数修改对应的坐标
                0 -> x = value
                1 -> y = value
                else -> throw java.lang.IndexOutOfBoundsException("Invalid coordinate $index")
            }
        }

        val mutablePoint = MutablePoint(10, 20)
        mutablePoint[1] = 42
        println(mutablePoint)// MutablePoint(x=10,y=42)

        // set 最后一个参数用来接收赋值语句中等号右边的值。
        // x(a,b) = c  ->  x.set(a,b,c)


        /**-------------------- 7.3.2 in 的约定 ----------------------*/
        // 代码清单7.11 实现in的约定
        data class Rectangle(val upperLeft: Point, val lowerRight: Point)

        operator fun Rectangle.contains(p: Point): Boolean {
            // 构建一个区间,检查坐标x是否属于这个区间,使用 until 函数来构建一个开区间
            return p.x in upperLeft.x until lowerRight.x &&
                    p.y in upperLeft.y until lowerRight.y
        }

        /*
        * in 右边的对象将会调用 contains 函数,in 左边的对象将会作为函数入参。
        * a in c -> c.contains(a)
        * in 10..20        [10,20] 用 10..20构建一个普通的闭区间。
        * in 10 until 20   [10,20) 开区间是不包括最后一个点的区间。
        */

        /**-------------------- 7.3.3 rangeTo 的约定 ----------------------*/
        /*
        * start..end  ->  start.rangeTo(end)
        * .. 运算符将被转换为 rangeTo函数的调用
        */

        // 这个函数返回一个区间,可以用来检测其他一些元素是否属性它。
//        operator fun <T : Comparable<T>> T.rangeTo(that: T): ClosedRange<T>

        // 代码清单7.12 处理日期的区间

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val now = LocalDate.now()
            // 创建一个从今天开始的10天的区间
            val closedRange = now..now.plusDays(10)
            // 检测一个特定的日期是否属于这个区间
            println(now.plusWeeks(1) in closedRange) // true

            // rangeTo 运算符的优先级低于算术运算符,但是最好把参数括起来
            val n = 9
            println(0..(n + 1))// 0..10

            (0..9).forEach {
                // 把区间括起来,来调用它的方法
                println(it)// 0123456789
            }


            /**-------------------- 7.3.4 在 for 循环中使用 iterator 的约定 ----------------------*/
            // in 在for循环中使用被执行迭代,转换成 list.iterator()
            // 这个库函数让迭代字符串成为可能
//         operator fun CharSequence.iterator():CharIterator
            for (c in "abc") {
                println(c)
            }

            // 代码清单7.13 实现日期区间的迭代器
            operator fun ClosedRange<LocalDate>.iterator(): Iterator<LocalDate> =
                    // 这个对象实现了遍历LocalDate元素的Iterator
                    object : Iterator<LocalDate> {
                        var current = start

                        // 注意,这里日期用到了compareTo约定
                        override fun hasNext() = current <= endInclusive

                        // 在修改前返回当前日期作为结果
                        override fun next() = current.apply {
                            // 把当前日期增加一天
                            current = plusDays(1)
                        }
                    }

            val ofYearDay = LocalDate.ofYearDay(2017, 1)
//            val dayOff = ofYearDay.minusDays(1)..newYear()
            // 对应的 iterator函数实现后,遍历daysOff
//            for (dayOff in daysOff) {
//                println(dayOff)
//            }
        }

7.4 解构声明和组件函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        class Point(val x: Int, val y: Int) {
            operator fun component1() = x
            operator fun component2() = y
        }


        // 解构声明:允许你展开单个复合值,并使用它来初始化多个单独变量
        val point = Point(10, 20)
        val (x, y) = point
        println(x)// 10
        println(y)// 20
        /*
        * 一个解构声明看起来像一个普通的变量声明,但它在括号中有多个变量。约定原理。
        * val (x,y) = point   :
        * val a = p.component1()
        * val b = p.component2()
        *
        * 主要场景之一:从一个函数返回多个值。
        */

        // 代码清单7.14 使用解构声明来返回多个值
        // 声明一个数据类来持有值
        data class NameComponents(val name: String, val extension: String)

        fun splitFileName(fullName: String): NameComponents {
            val result = fullName.split(".", limit = 2)
            // 返回也该数据类型的示例
            return NameComponents(result[0], result[1])
        }
        // 使用解构声明来展开这个类
        val (name, ext) = splitFileName("example.kt")
        println(name)// example
        println(ext)// ext

        // 代码清单7.15 使用解构声明来处理集合
        fun splitFilename(fullName: String): NameComponents {
            val (name, extension) = fullName.split(".", limit = 2)
            return NameComponents(name, extension)
        }
        // 标准库只允许使用此语法来访问一个对象的前五个元素,让一个函数能返回多个值有更简单的方法,使用标准库中的Pair和Triple类。


        /**-------------------- 7.4.1 解构声明和循环 ----------------------*/
        // 代码清单7.16 用解构声明来遍历 map
        // 使用这个语法来打印给定map中的所有条目
        fun printEntries(map: Map<String, String>) {
            for ((key, value) in map) {
                // 在 in 循环中用解构声明
                println("$key -> $value")
            }
            // 等同于这个
            for (entry in map.entries) {
                val key = entry.component1()
                val value = entry.component2()
                println("$key -> $value")
            }
        }

        val mapOf = mapOf("Oracle" to "Java", "JetBrains" to "Kotlin")
        printEntries(mapOf)
        // 使用了两个Kotlin约定:一个是迭代一个对象 一个是用于解构声明

7.5 重用属性访问的逻辑:委托属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
       /*
        * Kotlin中最独特和最强大的功能:委托属性
        * 委托是一种设计模式,操作的对象不用自己执行,而是把工作微委托给另一个辅助的对象。我们把辅助对象称为委托。
        */


        /**-------------------- 7.5.1 委托属性的基本操作 ----------------------*/
        // 基础语法:
//        class Foo {
        // 关键字 by 把属性关联上委托对象
//            var p: Type by Delegate()
//        }

        class Foo {
            // 编译器会自动生成一个辅助属性
//            private val delegate = Delegate()
            // p 的访问都会调用对应的 delegate 的getValue和setValue方法
//            var p: Type
//                set(value: Type) = delegate.setValue(..., value)
//                get() = delegate.getValue(...)
        }

        class Delegate {

            // getValue 包含了实现setter的逻辑
//        fun getValue(...): Type {
//            ...
//        }

            // setValue 包含了实现setter的逻辑
//        fun setValue(x: Int, any: Type) {
//            ...
//        }
//
        }

//        val foo = Foo()
        // 通过调用 delegate.getValue(...)来实现属性的修改
//        val oldValue = foo.p
        // 通过调用 delegate.setValue(...,newValue)来实现属性的修改
//        foo.p = newValue


        /**-------------------- 7.5.2 使用委托属性:惰性初始化和 by lazy() ----------------------*/
        // 惰性初始化时一种常见的模式,知道在第一次访问该属性的时候,才根据需要创建对象的一部分。

        class Email


        // 使用额外的 _emails 属性来实现惰性加载,在没有加载之前为null,然后加载为邮件列表

        // 代码清单7.17 使用支持属性来实现惰性初始化
        class Person(val name: String) {
            // _emails 属性用来保存数据,关联委托
            private var _emails: List<Email>? = null
            val emails: List<Email>
                get() {
                    if (_emails == null) {
                        // 访问时加载邮件
                        _emails = loadEmails(this)
                    }
                    //  如果已经加载,就直接返回
                    return _emails!!
                }

            fun loadEmails(person: Person): List<Email> {
                println("Load email for ${person.name}")
                return listOf()
            }
        }

        val p = Person("jingbin")
        p.emails// 第一次访问会加载邮件: Load email for jingbin
        p.emails
        /*
        * 这里使用了所谓的 支持属性技术。有一个属性 _emails 用来存储这个属性,而另一个email用来提供对属性的读取访问。
        * 这样代码有点啰嗦,而且线程不安全,kotlin有更好的方案,使用标准库函数 lazy 返回的委托。
        */


        // 代码清单7.18 用委托属性来实现惰性初始化
        class Person2(val name: String) {
            // lazy 的参数是一个Lambda,可以调用它来初始化这个值,且默认是线程安全的。
            val emails by lazy { loadEmail(this) }

            private fun loadEmail(person: Person2): List<Email> {
                println("Load email2 for ${person.name}")
                return listOf()
            }
        }


        /**-------------------- 7.5.3 实现委托属性 ----------------------*/
        // 代码清单7.19 使用 PropertyChangeSupport 的工具类
        open class PropertyChangeAware {

            protected val changeSupport = PropertyChangeSupport(this)

            fun addPropertyChangeListener(listener: PropertyChangeListener) {
                changeSupport.addPropertyChangeListener(listener)
            }

            fun removePropertyChangeListener(listener: PropertyChangeListener) {
                changeSupport.removePropertyChangeListener(listener)
            }
        }

        // 代码清单7.20 手工实现属性修改的通知
        class Person3(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
            var age: Int = age
                set(newValue) {
                    // field 标识符允许你访问属性背后的支持字段
                    val oldValue = field
                    field = newValue
                    changeSupport.firePropertyChange("age", oldValue, newValue)
                }

            var salary: Int = salary
                set(newValue) {
                    val oldValue = field
                    field = newValue
                    changeSupport.firePropertyChange("salary", oldValue, newValue)
                }
        }

        val p3 = Person3("jingbin", 30, 40000)
        // 关联监听器,用于监听属性修改
        p3.addPropertyChangeListener(PropertyChangeListener { it ->
            println("Property ${it.propertyName} changed" + "from ${it.oldValue} to ${it.newValue}")
        })
        p3.age = 35 // Property age changed form 30 to 35
        p3.salary = 60000 // Property salary changed form 40000 to 60000


        // 代码清单7.21 提过辅助类来实现属性变化的通知
        class ObservableProperty(val propName: String, var propValue: Int, val changeSupport: PropertyChangeSupport) {
            fun getValue(): Int = propValue
            fun setValue(newValue: Int) {
                val oldValue = propValue
                propValue = newValue
                changeSupport.firePropertyChange(propName, oldValue, newValue)
            }
        }

        class Person4(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
            val _age = ObservableProperty("age", age, changeSupport)
            var age: Int
                get() = _age.getValue()
                set(value) {
                    _age.setValue(value)
                }

            val _salary = ObservableProperty("salary", salary, changeSupport)
            var salary: Int
                get() = _salary.getValue()
                set(value) {
                    _salary.setValue(value)
                }
        }
        /*
        * 你创建了一个保存属性值的类,并在修改属性时自动触发更改通知。你删除了重复的逻辑代码,但是需要相当多的样板代码来为每个属性创建
        * ObservableProperty 实例,并把getter和setter委托给它。Kotlin的委托属性可以让你摆脱这些样板代码。
        */

        // 代码清单7.22 ObservableProperty 作为属性委托
//        class ObservableProperty2(var propValue: Int, val changeSupport: PropertyChangeSupport) {
//            operator fun getValue(p: Person5, prop: KProperty<*>): Int = propValue
//            operator fun setValue(p: Person5, prop: KProperty<*>, newValue: Int) {
//                val oldValue = propValue
//                propValue = newValue
//                changeSupport.firePropertyChange(prop.name, oldValue, newValue)
//            }
//        }

        // 代码清单7.23 使用委托属性来绑定更改通知
//        class Person5(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
//            var age: Int by ObservableProperty2(age, changeSupport)
//            var salary: Int by ObservableProperty2(salary, changeSupport)
//        }

        // 右边的对象被称为委托,Kotlin会自动将委托存储在隐藏的属性中,并在访问或修改属性时调用委托的geyValue,和setValue

        // 代码清单7.24 使用Delegates.observable来实现属性修改的通知
        class Person5(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
            private val observer = { prop: KProperty<*>, oldValue: Int, newValue: Int ->
                changeSupport.firePropertyChange(prop.name, oldValue, newValue)
            }
            var age: Int by Delegates.observable(age, observer)
            var salary: Int by Delegates.observable(salary, observer)
        }

        /*
        * by 右边的表达式不一定是新创建的实例,也可以是函数调用、另一个属性、或任何其他表达式,
        * 只要这个表达式的值,是能够被编译器用正确的参数类型来调用getValue和setValue的对象。
        */


        /**-------------------- 7.5.4 委托属性的变换规则 ----------------------*/
//        class C{
//            var prop: Type by MyDelegate()
//        }
//        val c = C()

        /*
        * MyDelegate 实例会被保存到一个隐藏的属性中,它被称为<delegate>。编译器也会将用一个KProperty类型的对象来代表这个属性,它被称为<property>。
        * 编译器生成的代码如下:
        */
//        class C {
//            private val <delegate> = MyDelegate()
//            var prop: Type
//                get() = <delegate>.getValue(this, <property>)
//                set(value:Type) = <delegate>.setValue(this,<property>,value)
//        }

        /*
        * val x = c.prop  -> val x = <delegate>.getValue(c, <property>)
        * c.prop = x      -> <delegate>.setValue(c, <property>, x)
        */


        /**-------------------- 7.5.5 在 map 中保存属性值 ----------------------*/
        // 代码清单7.25 定义一个属性,把值存在map
        class Person6 {
            private val _attributes = hashMapOf<String, String>()
            fun setAttribute(attrName: String, value: String) {
                _attributes[attrName] = value
            }

            // 从map手动检索属性
            val name: String
                get() = _attributes["name"]!!
        }

        val p6 = Person6()
        val data = mapOf("name" to "jingbin", "company" to "ali")
        for ((attrName, value) in data) {
            p6.setAttribute(attrName, value)
        }
        println(p.name) // jingbin

        // 代码清单7.26 使用委托属性把值存到map中
        class Person7 {
            private val _attributes = hashMapOf<String, String>()
            fun setAttribute(attrName: String, value: String) {
                _attributes[attrName] = value
            }

            // 把 map 作为委托属性
            val name: String by _attributes
        }

        /**-------------------- 7.5.6 框架中的委托属性 ----------------------*/
        // 代码清单7.27 使用委托属性来访问数据库列
        // user 对应数据库中的表
//        object Users : IdTable() {
        // name 和 age 对应数据库表的列
//            val name: varchar("name", length = 50).index()
//            val age = ingeter("age")
//        }

        // 每一个User示例对应表中的一个实体
//        class User(id: EntityID) : Entity(id) {
        // name 的值是数据库中对应那个用户的值
//            var name: String by Users.name
//            var age: Int by Users.age
//        }

总结

  • Kotlin 允许使用对应名称的函数来重载一些标准的数学运算,但是不能定义自己的运算符。
  • 比较运算符映射为 equals和 compareTo 方法的调用。
  • 通过定义名为 get set contains 的函数,就可以让你自己的类与Kotlin 的集合一样,使用[]和 in 运算符。
  • 可以通过约定来创建区间,以及迭代集合和数组。
  • 解构声明可以展开单个对象用来初始化多个变量,这可以方便地用来从函数返回多个值。它们可以自动处理数据类,可以通过给自己的类定义名为 componentN 的函数来支持。
  • 委托属性可以用来重用逻辑,这些逻辑控制如何存储、初始化、访问和修改属性值,这是用来构建框架的一个强大的工具。
  • lazy 标准库函数提供了一种实现惰性初始化属性的简单方法。
  • Delegates.observable 函数可以用来添加属性更改的观察者。委托属性可以使用任意 map 来作为属性委托,来灵活来处理具有可变属性集的对象。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Kotlin---解构与委托
通常,函数的返回值中只能返回一个对象,而我们可能要返回很多的数据。此时就可以用到解构
None_Ling
2018/12/07
6730
第11章 运算符重载与约定第11章 运算符重载与约定
我们在《第2章 Kotlin 语法基础》中已经学习过关于运算符的相关内容,本章将继续深入探讨Kotlin中的运算符的重载与约定。
一个会写诗的程序员
2018/08/17
9720
第11章 运算符重载与约定第11章 运算符重载与约定
运算符重载(看完这篇彻底掌握重载问题)
运算符重载:用同一个运算符完成不同的运算功能。 C++运算符重载的相关规定如下:
海盗船长
2020/08/27
9.8K1
手写编程语言-实现运算符重载
运算符重载其实也是多态的一种表现形式,我们可以重写运算符的重载函数,从而改变他们的计算规则。
crossoverJie
2022/12/20
3690
手写编程语言-实现运算符重载
Kotlin委托
Kotlin中有委托,这个C#中也有,不过对于学Java的童鞋来说,这是什么鬼啊,到底是干什么用的… 在委托模式中,当有两个对象参与处理同一个请求是,接受请求的对象将请求委托给另一个对象来处理。委托模式已证明是实现继承的一个很好的替代方式。Kotlin中委托分为类委托和委托属性,Kotlin官方库也封装了一些常用的委托。
haifeiWu
2018/09/11
1.5K0
Kotlin Vocabulary | Kotlin 内建代理
代理可以帮助您将任务委托给其他对象,从而带来更佳的代码复用性,您可以从 我们之前的文章 了解到更多信息。Kotlin 不仅可以让您通过 by 关键字轻松实现代理,还在标准库中提供了像 lazy()、observable()、vetoable() 以及 notNull() 这样的内建代理。接下来就让我们开始了解这些内建代理的使用,以及其内部的实现原理。
Android 开发者
2022/03/09
1K0
第2章 Kotlin 语法基础第2章 Kotlin 语法基础
人与人之间通过语言来交流沟通,互相协作。人与计算机之间怎样“交流沟通”呢?答案是编程语言。一门语言有词、短语、句子、文章等,对应到编程语言中就是关键字、标识符、表达式、源代码文件等。通常一门编程语言的基本构成如下图所示
一个会写诗的程序员
2018/08/17
2.8K0
第2章 Kotlin 语法基础第2章 Kotlin 语法基础
你真的懂 Kotlin 中的 by 关键字吗?3分钟搞懂精髓
在Kotlin中,by 关键字主要用于实现委托模式。委托模式是一种设计模式,它允许一个对象将部分职责委托给另一个对象。在Kotlin中,by 关键字提供了一种简洁的语法,使得委托的实现变得更加轻松。
Rouse
2024/02/06
1.2K0
你真的懂 Kotlin 中的 by 关键字吗?3分钟搞懂精髓
【Android进阶】Kotlin笔记
这类似于只支持加法的抽象语法树,Expr代表一个表达式,也就是语法树里的一个节点,同时Num代表数字节点,它只可能是叶子,Sum代表加法节点,不可能是叶子。
易寒
2022/01/10
7710
C++运算符重载之加号运算符重载
加号运算符重载 作用:实现两个自定义数据类型相加的运算 1.成员函数实现 + 号运算符重载 class Person { public: Person() {}; Person(int a, int b) { this->m_A = a; this->m_B = b; } //1.成员函数实现 + 号运算符重载 Person operator+(const Person& p) { Person temp; temp.m_A = this->m_A + p.m_A;
CtrlX
2022/08/10
8040
Kotlin | 一份10万字的随查笔记,妈妈再也不担心我不会Ctrl+F了
关于Kotlin相关记录,如果有意查看我的github,其超10w字(其中8w是代码吗,哈哈)。。
Petterp
2022/03/18
2.9K0
Kotlin | 一份10万字的随查笔记,妈妈再也不担心我不会Ctrl+F了
Kotlin 基础 | 委托及其应用
委托是常见的模式,它和编程语言无关,即把本来自己做的事情委托给另一个对象去做。装饰者模式和代理模式都通过委托复用了行为。Kotlin 在语言层面支持了委托,这一篇结合实例介绍一下 Kotlin 的委托。
Rouse
2021/05/28
1K0
C/C++开发基础——运算符重载
运算符重载在C++的特性中并不算很特别,这次把它单独拿出来作为一个章节是想借助运算符重载的一些样例来回顾一下C++的一些语法特性,代码量比较多,但是都很经典。
Coder-ZZ
2023/11/21
1930
C/C++开发基础——运算符重载
Kotlin基础之委托
委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。 类委托 委托模式是替换继承的较好的设计模式,Kotlin天生支持委托模式,无须任何模板代码。类Derived可以继承Base接口,委托所有public方法给指定对象。例如: interface Base { fun print() } class BaseImpl(val x: Int) : Base { override fun print() { print
xiangzhihong
2018/02/08
8530
Kotlin修炼指南(五)—Delegates
委托,是一种比较常见的设计模式,通常采用接口或者抽象类的方式来实现,在Java代码中,一般使用接口来进行封装,而在kotlin中,可以通过委托机制来实现更加方便的委托模式。
用户1907613
2021/01/29
8550
Kotlin修炼指南(五)—Delegates
Kotlin的委托属性和区间
委托属性 委托属性 是一种通过委托实现拥有 getter 和可选 setter 的 属性,并允许实现可复用的自定义属性。例如: class Example { var p: String by Delegate() } 委托对象必须实现一个拥有 getValue() 方法的操作符,以及 setValue() 方法来实现读/写属性。些方法将会接受包含对象实例以及属性元数据作为额外参数。当一个类声明委托属性时,编译器生成的代码会和如下 Java 代码相似。 public final class Exam
xiangzhihong
2018/02/06
1.4K0
【Android进阶】Kotlin面向对象
在Kotlin中,我可以声明普通类、数据类、静态类,它也有抽象类和接口,其中abstract关键字只能作用在普通类。
易寒
2022/01/26
5550
C++运算符重载(五)之关系运算符重载
正常情况下如果想比较两个日期大小是无法实现的,这是因为运算符默认都是给内置类型用的。
CtrlX
2022/09/21
7830
《Kotin 极简教程》第7章 面向对象编程(OOP)(2)《Kotlin极简教程》正式上架:
在上面的代码中,我们通过向注解类添加元注解(meta-annotation)的方法来指定其他属性:
一个会写诗的程序员
2018/08/17
1.6K0
运算符重载python_Python运算符重载
Welcome to the tutorial on Python Operator Overloading. As we have already learnt about Python Class, we are going to learn another interesting feature of object oriented python today.
用户7886150
2020/11/27
1.5K0
相关推荐
Kotlin---解构与委托
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验