您的位置:首页 > 其它

Kotlin-属性和字段

2017-06-30 09:21 393 查看

属性声明

在Kotlin中的类都有属性,他们可以用val声明为不可变的变量,也可以用var声明为可变的变量

class Mk{
var name:String="MichaelKoo"
var street:String="GZ"
val sex="Man"
...
}


要想使用这些属性也是很简单,我们可以根据属性名来引用,它就像Java中的变量。

fun copy(mk:Mk):Mk{
val result=Mk()
result.name=mk.name
result.street=mk.street
result.sex=mk.sex
//...
return result
}


Getter 和 Setters

声明属性的完整语法是

var <propertyName>[:PropertyType][=property_initializer]
[<getter>]
[<setter>]


其中,initializer和getter、setter都是可选的,当然属性的类型在有初始值的时候也是可以省略的

举个例子:

var allBy:Int?//错误写法
var allBy=1 //正确写法


其中错误写法的是因为没有初始值,从而导致没有隐藏的setter和getter,正确写法的话,是因为有初始值,那么肯定也是有setter和getter。

当然肯定会有人嫌弃像Java中的那样显示的setter和getter,这里Kotlin提供了可以自定义setter和getter的方法。比如自定义getter:

var size=11
val isEmpty:Boolean
get() = this.size==0


有自定义的getter,肯定也有自定义的setter

var changeSize:Int
get()=changeSize
set(value){
size=value
}


隐性支持字段

在Kotlin中的类是没有字段这个说法的。然而,有时候在用自定义访问器的时候还是需要用到字段的。为了这些情况,kotlin提供了field关键字,只要访问field标识的时候就会自动转换

var counter=0
set(value){
if(value >= 0)field=value
}


field标识符只能用在属性访问器中哦

隐性支持属性

If you want to do something that does not fit into this “implicit backing field” scheme, you can always fall back to having a backing propert

如果你要做的一些事情,在“隐性支持字段”章节中得不到解决,你随时都有一个支持性

private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap() // Type parameters are inferred
}
return _table ?: throw AssertionError("Set to null by another thread")
}


In all respects, this is just the same as in Java since access to private properties with default getters and setters is optimized so that no function call overhead is introduced

在所有方面,这和在Java中通过默认的getter和setter来访问私有属性,从而达到没有引入函数调用开销的优化

编译时常数

Properties the value of which is known at compile time can be marked as compile time constants using the const modifier. Such properties need to fulfil the following requirements:

用const修饰符修饰的属性在编译时就可以知道属性的值,这种属性称为编译时常量,这些属性通常需要满足一下要求:

Top-level or member of an object

对象的顶级或成员

Initialized with a value of type String or a primitive type

初始化值是字符串类型或基本类型

No custom getter 没有自定义的getter

Such properties can be used in annotations*这些属性可以用于注解中*

如下示例:

const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"

@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }


延迟初始化属性

Normally, properties declared as having a non-null type must be initialized in the constructor.

一般来说,一个非空类型的属性都需要在构造方法中进行初始化。

However, fairly often this is not convenient.

然而通常情况下这并不方便.

For example, properties can be initialized through dependency injection, or in the setup method of a unit test.

例如,属性通常都依赖于注入来初始化或在测试用例中的setup方法

In this case, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class

在这些情况下,在构造方法中你必须有初始化方法,并且你在类中的使用也是避免不了要进行非空检查。

To handle this case, you can mark the property with the lateinit modifier:

为了解决这个情况,你可以使用lateinit来修饰这个属性:

public class MyTest {
lateinit var subject: TestSubject

@SetUp fun setup() {
subject = TestSubject()
}

@Test fun test() {
subject.method()  //直接引用
}
}


The modifier can only be used on var properties declared inside the body of a class (not in the primary constructor), and only when the property does not have a custom getter or setter. The type of the property must be non-null, and it must not be a primitive type.

这个修饰符只能用在被var声明的属性中(不可以在主要构造方法中),并且这个属性还不能有自定义的getter和setter.这个属性的类型不可以为空,并且它还不能是基本类型.

Accessing a lateinit property before it has been initialized throws a special exception that clearly identifies the property being accessed and the fact that it hasn’t been initialized.

在没有初始化前就使用这些属性,同样也会报异常,一般有可能会是

kotlin.UninitializedPropertyAccessException: lateinit property dd has not been initialized
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: