Kotlin快速入门系列9

Kotlin对象表达式和对象声明

对象表达式

有时,我们想要创建一个对当前类有些许修改的对象同时又不想重新声明一个子类。如果是Java,可以用匿名内部类的概念来解决这个问题。kotlin的对象表达式和对象声明就是为了实现这一点(创建一个对某个类做了轻微改动的类的对象,且不需要去声明一个新的子类)。

对象表达式的格式:

Object[: 若干个父类型,中间用逗号分隔]

例如下例常见的,通过对象表达式实现的将一个匿名内部类的对象用于方法的参数中:

computer.addMouseListener(object : MouseAdapter() {override fun mouseClicked(e: MouseEvent) {// ...}override fun mouseRolled(e: MouseEvent) {// ...}
})

通过对象表达式可以越过类的定义直接得到一个对象:

fun main(args: Array<String>) {val site = object {var tips: String = "谷歌大法好"var url: String = "www.Google.com"}println(site.tips)println(site.url)
}

对应的控制台输出为:

如果超类有构造器,则需要传入合适的参数。多个超类在冒号之后使用逗号分隔,大抵格式如下:

open class BaseA(x: Int){public open val num: Int = x
}interface InterfaceB {...}val ab: A = object : BaseA(1) , InterfaceB{override val num = 15
}

用作类型的匿名对象,只能在局部和私有声明中。如果使用匿名对象作为public函数的返回值,或public属性的类型,则函数或属性的实际类型实际为匿名类的超类或Any(未声明任何超类)。匿名对象添加的成员不能被访问。下面是一个官网的例子:

class Demo{// 私有函数,所以返回类型为匿名对象类型private fun foo() = object {val x: String = "foo"}// Public函数,返回类型为Anyfun publicFoo() = object {val x: String = "FOO"}fun bar() {val x1: String = foo().x  // 有效val x2: String = publicFoo().x // 提示错误:无法引用x}
}

对象声明

在Kotlin中,使用 object 关键字来声明一个(单例)对象。这点跟Java是完全不一样的,在Java中,必须先有类,然后才能new出该类的对象并生成实例,也就是声明类和创建对象是两个分开的步骤,并有先后次序。在Kotlin中,我们可以使用object关键字在声明定义一个类的同时创建出一个对象,这就是所谓的对象声明

使用方法极其简单,在 object 关键字后跟⼀个名称即可,这样就直接声明了一个单例对象。

object DataProviderManager {fun registerDataProvider(provider: DataProvider) {
// ……}val allDataProviders: Collection<DataProvider>get() = // ……
}

要引⽤该对象,直接使⽤其名称即可:

DataProviderManager.registerDataProvider(……)

注意这里是单例,当你定义两个不同的变量来获取这个对象时,你会发现你并不能得到两个不同的变量,如下例我们只对一个对象实例进行了属性更改,但打印两个对象实例都会得到更改的属性:

object WebSite {var url:String = ""val web: String = "谷歌大法好"
}
fun main(args: Array<String>) {var s1 = WebSitevar s2 = WebSites1.url = "www.Google.com"println(s1.url)println(s2.url)
}

对应的控制台输出为:

与对象表达式不同的是,当对象声明在另一个类的内部时,这个对象并不能通过外部类的实例访问到该对象,而只能通过类名来访问,同样该对象也不能直接访问到外部类的方法和变量。

object WebSite {var web = "谷歌大法好"object DeskTop{var url = "www.Google.com"fun showName(){print{"desk legs $web"} // 错误,不能访问到外部类的方法和变量,打印结果为:Function0<java.lang.String>}}
}
fun main(args: Array<String>) {var site = WebSitesite.DeskTop.url // 提示错误,不能通过外部类的实例访问到该对象WebSite.DeskTop.url // 调用方式正确
}

伴生对象 

跟Java不同,在kotlin中,类是没有static方法的。多数情况下,Kotlin推荐的做法是使用包级别的函数作为静态方法。这里就引申除了另外一个关键字,companion。

在类内部的对象声明可以用 companion 关键字标记,这样它就与外部类关联在一起,我们可以直接通过外部类访问到对象的内部元素。

class DemoClass {companion object Factory {fun create(): DemoClass = DemoClass()}
}val instance = DemoClass.create()   // 变量可直接访问到对象的内部元素

我们可以直接省略掉该对象的对象名,然后使用 companion 替代需要声明的对象名:

class DemoClass {companion object {}
}val instance = DemoClass.Companion

这里需要注意的是,一个类里面只能声明一个内部关联对象,即关键字 companion 只能使用一次。

伴生对象的成员看起来像其他语言的静态成员,但在运行时他们仍然是真实对象的实例成员。在 JVM 平台,如果使⽤ @JvmStatic 注解,你可以将伴⽣对象的成员⽣成为真正的静态⽅法和字段。

差异性

最后总结下,对象表达式和对象声明之间有一个重要的语义差别:

· 对象表达式是在使用他们的地方立即执行的;

· 对象声明是在第一次被访问到时延迟初始化的;

· 伴生对象的初始化是在相应的类被加载(解析)时,与 Java 静态初始化器的语义相匹配。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/441333.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【开源操作系统】上海道宁为您带来稳定、安全、开源和易用的操作系统——Ubuntu,为您的数字化生活保驾护航

Ubuntu是 源于非洲的一种传统价值观 意为“人性、关爱和共享” 这种价值观在 开源、稳定、安全、易用的 Ubuntu操作系统中 得到了完美的体现 除此之外&#xff0c;Ubuntu还具有 强大的安全性 它自带了诸多安全功能 如防火墙、加密文件系统等 可以有效地保护用户的隐私…

java组装复杂的map结构

如下图数据库查出来的记录要组装成如下图所示的map结构。 直接上代码 package com.rt.test.other;import org.apache.commons.lang.StringUtils;import java.util.*;public class TestMap {public static void main(String[] args) {Map<String,String> mapnew LinkedHa…

15EG使用vivado2023.1点亮PL led

打开VIVADO2023.1 创建一个新的工程 输入项目名称和地址&#xff0c;下面那个选项为是否使用项目名称新建一个文件夹&#xff0c;我这里已经建了一个pl_only_led文件夹&#xff0c;所以不勾选 选择RTL工程&#xff0c;勾选不添加文件 搜索15eg&#xff0c;选择xqzu15eg-ffrb115…

treeview

QML自定义一个TreeView&#xff0c;使用ListView递归 在 Qt5 的 QtQuick.Controls 2.x 中还没有 TreeView 这个控件&#xff08;在 Qt6 中出了一个继承自 TableView 的 TreeView&#xff09;&#xff0c;而且 QtQuick.Controls 1.x 中的也需要配合 C model 来自定义&#xff0c…

【数论】【分类讨论】【C++算法】1611使整数变为 0 的最少操作次数

作者推荐 【动态规划】【字符串】【行程码】1531. 压缩字符串 涉及知识点 数论 数学 分类讨论 LeetCoce1611. 使整数变为 0 的最少操作次数 给你一个整数 n&#xff0c;你需要重复执行多次下述操作将其转换为 0 &#xff1a; 翻转 n 的二进制表示中最右侧位&#xff08;第…

Ubuntu 22.04 中文乱码解决方案

sudo apkg-reconfigure locales 按空格键选中

[ project.config.json 文件内容错误] project.config.json: libVersion 字段需为

解决方法&#xff1a; 在manifest文件的mp-weixin中添加 "libVersion": "latest" 即可

如何使用postman进行接口自动化测试?

1、什么是自动化测试&#xff1f; 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试&#xff0c;模拟人去操作软件界面&#xff0c;把人从简单重复的劳动中解放出来&#xff0c;本质是用代码去测试另一段代码&#xff0c;属于一种软件开发工作&a…

idea报错 :(java: 找不到符号)

java: 找不到符号 符号: 变量 adminService 位置: 类 com.example.controller.WebController 查到网上一个办法&#xff1a;因为项目是maven&#xff1a;先点clean在点package

283. Move Zeroes(移动零)

题目描述 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 问题分析 从后向前&#xff0c;记录第一个非0的数字的下标&#xff0c;然后从…

Uniapp小程序端打包优化实践

背景描述&#xff1a; 在我们最近开发的一款基于uniapp的小程序项目中&#xff0c;随着功能的不断丰富和完善&#xff0c;发现小程序包体积逐渐增大&#xff0c;加载速度也受到了明显影响。为了提升用户体验&#xff0c;团队决定对小程序进行一系列打包优化。 项目优化点&…

产品原型图设计规范大全

目前&#xff0c;市场上许多产品经理或设计师都在使用一些优秀的原型设计规范&#xff0c;这些规范几乎涵盖了原型设计的许多方面。一套好的、完整的原型设计规范可以统一产品设计风格&#xff0c;检验产品的可用性&#xff0c;有效提高产品经理绘制原型图的效率&#xff0c;更…