Kotlin学习之-5.2 属性和成员
来源:互联网 发布:苏联歌曲 知乎 编辑:程序博客网 时间:2024/06/02 05:02
Kotlin学习之-5.2 属性和成员
定义属性
Kotlin中,类可以有属性。它们既可以用var
关键字定义成变量,也可以用val
关键字定义成只读量。
class Address { var name: String = ... var street: String = ... var city: String = ... var state: String? = ... var zip: String = ...}
使用一个属性,只要简单的用它的名字引用即可,就像Java中的成员一样。
fun copyAddress(address: Address): Address { val result = Address() // Kotlin中没有'new' 关键字 result.name = address.name result.street = address.street //... return result}
Getter 和Setter
定义属性完整语法结构如下:
var <propertyName>[: <PropertyType>] [= <property_initializer>] [<getter>] [<setter>]
构造器、getter 和setter都是可选项。如果属性的类型可以从构造器中推断出来的话,那么属性的类型也是可选的。示例如下:
var allByDefault: Int? // error: 需要显式的构造器。 有默认的getter 和settervar initialized = 1 // 类型是Int。 有默认的getter 和setter
只读属性的语法和变量属性的的语法有两点不同: 定义是用val
而不是var
,并且没有setter 方法
val simple: Int? // 类型是Int,默认的getter方法,必须在构造函数中初始化。val inferredType = 1 // 类型是Int, 默认的getter方法。
我们可以在属性定义时自定义getter方法,和普通的函数非常像。示例如下:
val isEmpty: Boolean get() = this.size == 0
自定义setter方法示例如下:
var stringRepresentation: String get() = this.toString() set(value) { setDataFromString(value) // 解析字符串并且赋值给其他属性 }
一般情况,setter方法的参数名是value
,但是也可以选择一个其他名字。
从Kotlin v1.1开始,如果属性类型可以从getter方法中推断出来,那么定义的时候可以省略属性类型。
val isEmpty() get() = this.size == 0 // 推断的类型Boolean
如果要更改函数的可见性或者添加注解,但是不需要干煸默认的实现,可以定义访问函数但不定义函数主体。
var setterVisibility: String = "abc" private setvar setterWithAnnotation: Any? = null @inject set
Backing Fields
Kotlin中,类没有成员。但是有时候使用自定义访问函数时也需要一个’backing field’。 在这些用法中,Kotlin提供一个自动的’backing field’, 它可以用field
关键字来访问。
var counter = 0 set(value) { if (value >= 0) field = value }
field
描述符只能用在属性的访问。
属性会产生一个’backing field’,如果属性有至少一个默认实现的访问函数,或者自定义的访问函数使用了field
描述符来访问这个属性。
例如,下面的例子中没有没有’backing field’
val isEmpty: Boolean get() = this.size == 0
Backing Properties
如果你需要做的事情不符合隐式backing field模式,那么可以使用backing property
private var _table: Map<String, Int>? = nullpublic val table: Map<String, Int> get() { if (_table == null) { _table = HashMap() // 类型参数是推断出来的 } return _table ?: throw AssertionError("Set to null by another thread") }
总的来说,这和Java是一样的,使用默认的getter和setter方法访问私有的属性会被优化,从而没有函数调用的负担。
编译期常量
属性的值在编译期就确定的话,用const
修饰符来表示成编译期常量。这样的属性需要满足如下要求。
- 顶级的或者是一个
object
的成员 - 是用
String
类型或者基础类型初始化的 - 没有自定义getter方法
这样的属性可以在注解中使用
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }
延迟初始化的属性
一般情况,被定义成非空的属性必须在构造函数中初始化。但是,这样通常不太方便。例如,属性可以在依赖注入的时候被初始化,或者在单元测试的setup方法中初始化。 在这种情况,就不能再构造函数中提供一个非空的初始化器,但是你仍然想要在引用属性的时候避免空指针检查。
处理这种情况,需要用lateinit
描述符来标识这个属性。
public class MyTest { lateinit var subject: TestSubject @SetUp fun setup() { subject = TestSubject() } @Test fun test() { subject.method() }}
延迟初始化lateinit
描述符只能用在var
属性,并且属性不能有自定义的getter和setter。属性的类型必须是非空的,并且不能是基础类型。
在属性初始化之前,访问一个延迟初始化lateinit
的属性,会抛出一个特殊的异常,该异常表明属性在访问的时候,还没有初始化。
代理属性
最常用的属性就是简单地读取或者写入backing field。 另外,使用自定义的getter和setter可以实现属性任意的操作。 除了这两种情况,还有一些常见的用法。例如,延迟初始化的值,用一个给定的关键字从一个map中获取对应的值,访问数据库,通知监听器等等。
这些常用的行为和操作可以通过库的方式来实现。这可以使用代理属性的方式来实现。
PS,我会坚持把这个系列写完,有问题可以留言交流,也关注专栏Kotlin for Android Kotlin安卓开发
- Kotlin学习之-5.2 属性和成员
- Kotlin 学习之属性和字段
- Kotlin 官方学习教程之属性和字段
- Kotlin学习之-5.13 代理属性
- Kotlin学习(三): 属性和字段
- OC学习之Runtime之一成员变量和属性
- Kotlin 变量和属性
- kotlin属性和变量
- Kotlin-属性和字段
- Kotlin 属性和域
- Kotlin 字段和属性
- Kotlin学习之object表达式和声明
- Kotlin学习之-5.1 类和继承
- Kotlin 学习之包和导入
- Kotlin学习笔记——属性和字段
- Kotlin 从学习到 Android 第七章 属性和字段
- Kotlin编程之扩展属性和扩展伴生对象
- runtime之属性和成员变量
- kotlin学习小记--单例
- JEESZ分布式框架简介---开发环境部署
- Scala入门到精通——类型参数(一)
- Mybatis自动生成代码
- 【转载】Java位运算总结
- Kotlin学习之-5.2 属性和成员
- java设计模式:五、单例模式
- Java代码审计之文件包含
- 定制自己的Log日志工具—轻松控制log打印
- JAVA-设计模式之简单工厂模式
- Hibernate学习目录
- I2C设备应用层读写
- [Unity&]缺少引用空间MouseLook 的解决办法
- css的counter-increment和counter-reset