翻译说明:java
原标题: Kotlin: should I define Function or Property?缓存
原文地址: blog.kotlin-academy.com/kotlin-shou…session
原文做者: Igor Wojda数据结构
最近,我对属性和函数用法方面感到困惑。这是一个很好的机会去介绍有关Kotlin属性的概念。那么问题来了,何时使用函数或者使用属性呢?我建议你遵循如下最简单的规则:ide
让咱们进一步探讨他们。属性表明着一个能够描述对象状态的数据结构,例如: Person对象能够有name、lastName 和 weight属性。函数
class Person (var name:String, var lastName:String, var weight:Double)
复制代码
咱们还能够建立一个派生属性,用于返回fullName,它是由name和lastName两个属性组合而成的。post
class Person (var name:String, var lastName:String, var weight:Double) {
val fullName = "$name $lastName"
}
复制代码
在上述例子中,在Person对象建立期间,属性值fullName仅仅被赋值一次。有时这是一个理想的行为,可是在这个例子中,当咱们去改变了name或者lastName的属性值时,被存储在fullName的值不会被更新。幸运的是,Kotlin也提供了使用getter或者setter去自定义属性访问器的能力。在下面例子中fullName属性的值会在每一次被访问的时候都会被赋值。学习
class Person (var name:String, var lastName:String, var weight:Double) {
val fullName
get() = "$name $lastName"
}
复制代码
函数,在另外一方面包含了对象全部能够被执行的行为或者动做。咱们的Person类能够有 run(),walk() 和 jump() 的方法。ui
class Person () {
fun run() { /*doSth*/ }
fun walk() { /*doSth*/ }
fun jump() { /*doSth*/ }
}
复制代码
重要的是须要注意,该方法可能会有一个间接修改对象状态的反作用,例如咱们每调用一次 jump() 方法都会使得person对象中的weight属性值减小0.1this
class Person (var name:String, var lastName:String, var weight:Double) {
//..
fun jump() {
weight -= 0.1
/*doSth*/
}
}
复制代码
若是你仍然困惑于何时使用属性或函数,那么接下来将会从外部调用者的角度去回答这个问题。咱们先暂时无论其内部的实现(一个属性被存储在哪里或者行为怎么实现的)而且须要更加简单地去看待外部的API(相似于加入第三方的库到项目中,咱们仅仅关注其库提供API便可)
person.name = "Igor"
person.weight = 79
person.jump()
person.jump()
person.jump()
复制代码
使用Kotlin属性好处之一在于属性访问器更加简洁的语法(咱们可使用height 去替代getHeight()/setHeight()方法),此外就是getter和setter方法更加接近于属性的声明,不像Java,咱们一般会在一个类的顶部定义成员属性,而后在其下面定义getter和setter方法。我喜欢属性委托这个特性,它能够提升复用代码的能力。咱们能够初始化一个变量仅仅当它被须要使用的时候(lazy delegate) ,不管何时属性的值发生变化,能够执行一些动做(Observable delegate)或者使用自定义委托实如今另外一对象(Android shared preferences, map, browser session, database…) )中简单地存储咱们属性.
不错的是Kotlin容许咱们在接口中均可以使用函数和属性
//BAD
class Person () {
private var weight:Double = 0
fun setWeight(weight:Double) {
this.weight = weight
}
fun getWeight(): Double {
return weight
}
}
//GOOD
class Person (var weight:Double)
复制代码
当咱们看到一个以set为前缀(如: setHeight())开头的方法、只有一个参数而且被指定为private的变量或者以get为前缀(如: getHeight())开头的方法、返回一个被指定为private的变量时,咱们应该定义一个属性来替代它。
指南: 如何作这个决定?
每次你想去声明一个新的函数时,你须要问本身两个问题:
这里还有一系列额外来自Effective Java(若是没记错的话)的帮助指南让咱们了解定义属性优于函数。
以上的指南应该能够给你一个不错的建议,何时去使用函数或者属性。在一开始,定义属性或许有点不适应(特别是Java开发者),可是相信我--一段时间后,这个决定是明智的。
咱们都知道Kotlin这门语言流行不久,目前在国内没有被大面积应用于实际项目中,而在国外这门语言则很是流行,有不少公司也在大量运用它,在今年的Google IO上,Google官方说他们有35%的工程师喜欢使用Kotlin,因此国外一些Kotlin相关的博客质量都还不错。也包括了他们使用Kotlin在一些实际项目中的经验。一门语言必定得在实际应用中体现它的价值,因此有必要去学习学习。因为国外博客都是英文的,因此我作了一些翻译的事情以及我对这边博客感觉并提炼一些重要点出来。欢迎继续关注~
咱们知道学习Kotlin的语法时候与应用于开发是有差距的,在使用过程当中会遇到各类选择的问题,好比这篇博客是阐述在Kotlin中咱们何时去定义一个属性,何时去定义一个函数呢?这个问题是从基本语法学习中得不到的,得从实际需求和使用经验中去体会,对于Java转Kotlin的初学者而言,很容易受到Java语言思想去任意定义函数。由于在Java中是没有自定义属性访问器一说,改变状态惟有经过函数呗。而在Kotlin提供了一个更为简单方式去改变属性状态。因此当你还在用Java语言思想在使用Kotlin的语言,不妨真正去思考一下使用Kotlin来写优点在哪里?
关于何时用函数何时用属性: 描述状态时,用属性;描述行为时,用函数。
看个例子再次体会下(关于自定义属性访问器的知识能够查阅我以前的浅谈系列博客中变量和常量那篇):
Java部分代码例子实现
//对于Java而言没有Kotlin中属性访问器之说,对于须要每次访问时都
//必须保证拿到最新状态时,Java中惟一好的处理方式就是定义函数,例如isIdling()、isEnded()方法
class VideoPlayer{
public boolean isIdling() {//描述的是状态
return this.mPlayer != null && this.mPlayer.getPlaybackState() == 1;
}
public boolean isEnded() {//描述的是状态
return this.mPlayer != null && this.mPlayer.getPlaybackState() == 4;
}
public void play(){//描述的是行为动做
//do sth
}
public void resume(){//描述的是行为动做
//do sth
}
}
//调用
if (mVideoPlayer.isEnded() || mVideoPlayer.isIdling()) {
mVideoPlayer.play();
}else{
mVideoPlayer.resume();
}
复制代码
Kotlin代码例子实现
class VideoPlayer{
var mIsIdling = false//描述的是状态
get() = this.mPlayer != null && this.mPlayer.getPlaybackState() == 1
var mIsEnded = false//描述的是状态
get() = this.mPlayer != null && this.mPlayer.getPlaybackState() == 4
fun play(){//描述的是行为动做
//do sth
}
fun resume(){//描述的是行为动做
//do sth
}
}
//调用
if (mVideoPlayer.mIsEnded || mVideoPlayer.mIsIdling) {
mVideoPlayer.play()
}else{
mVideoPlayer.resume()
}
复制代码
欢迎关注Kotlin开发者联盟,这里有最新Kotlin技术文章,每周会不按期翻译一篇Kotlin国外技术文章。若是你也喜欢Kotlin,欢迎加入咱们~~~