声明属性
在类里面使用var或者val就可以声明了。
public class Address {
public var name: String = ...
public var street: String = ...
public var city: String = ...
public var state: String? = ...
public var zip: String = ...
}
只需要将成员变量定义成一个变量,默认是 public 的。编译器会自动生成 getter 和 setter 方法。所以上面的属性编译器默认添加了getter 和 setter 方法。
属性的使用
fun copyAddress(address: Address): Address {
val result = Address() // there's no 'new' keyword in Kotlin
result.name = address.name // accessors are called
result.street = address.street
// ...
return result
}
上面对属性的访问,并不是像Java里面一样,直接访问属性的本身,而是默认调用了getter 和 setter 方法。
Getters and Setters
完整的属性声明如下:
var <propertyName>: <PropertyType> [= <property_initializer>]
[<getter>]
[<setter>]
其中initializer, getter 和 setter都是可选的。var是允许有getter 和 setter方法,如果变量是val声明的,它类似于Java中的final,所以如果以val声明就不允许有setter方法。
val isEmpty: Boolean
get() = this.size == 0
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // parses the string and assigns values to other properties
}
下面举个例子:
class Person {
var name: String = "abc"
get() = field.toUpperCase()
set(value){
field = "Name: $value"
}
}
fun main(args: Array<String>) {
var customer: Person = Person()
println(customer.name) // ABC
customer.name = "aaa"
println(customer.name) //NAME: AAA
}
对于属性,如果你想改变访问的可见性或者是对其进行注解,但是又不想改变它的默认实现,那么你就可以定义set和get但不进行实现。
var setterVisibility: String = "abc" // Initializer required, not a nullable type
private set // the setter is private and has the default implementation
var setterWithAnnotation: Any?
@Inject set // annotate the setter with Inject
Backing Fields
在上面例子中定义的Person类里面,属性的get和set方法里面使用了一个field,它是一个自动的返回字段,代表的就是属性。
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0)
field = value
}
field只有在访问的时候才会产生,其他时候是不会产生的。
Backing Properties
如果Backing Fields不适用的话,其实可以直接使用返回属性就可以了。
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")
}
延迟初始化属性
对于非空类型的属性是必须初始化的。如果我们希望延迟进行初始化,就可以使用lateinit关键字了。
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method() // dereference directly
}
}