《Kotlin核心编程》 ——3.1.3 主从构造方法
3.1.3 主从构造方法
我们似乎遗漏了另一些常见的情况。有些时候,我们可能需要从一个特殊的数据中来获取构造类的参数值,这时候如果可以定义一个额外的构造方法,接收一个自定义的参数会显得特别方便。
同样以鸟为例,先把之前的Bird类简化为:
class Bird(age: Int) {
val age: Int
init {
this.age = age
}
}
假设当前我们知道鸟的生日,希望可以通过生日来得到鸟的年龄,然后创建一个Bird类对象。如何实现?
第1种方案是在别处定义一个工厂方法,如:
import org.joda.time.DateTime
fun Bird(birth: DateTime) = Bird(getAgeByBirth(birth))
应该在哪里声明这个工厂方法呢?这种方式的缺点在于,Bird方法与Bird类在代码层面的分离显得不够直观。
一种改进方案是在Bird类的伴生对象中定义Bird方法。我们会在后续的节中介绍这种技术。
显然我们可以像Java那样新增一个构造方法来解决这个问题。其实Kotlin也支持多构造方法的语法,然而与Java的区别在于,它在多构造方法之间建立了“主从”的关系。现在我们来用Kotlin中的多构造方法实现这个例子:
import org.joda.time.DateTime
class Bird(age: Int) {
val age: Int
init {
this.age = age
}
constructor(birth: DateTime) : this(getAgeByBirth(birth)) {
...
}
}
来看看这个新的构造方法是如何运作的:
通过constructor方法定义了一个新的构造方法,它被称为从构造方法。相应地,我们熟悉的在类外部定义的构造方法被称为主构造方法。每个类可最多存在一个主构造方法和多个从构造方法,如果主构造方法存在注解或可见性修饰符,也必须像从构造方法一样加上constructor关键字,如:
internal public Bird @inject constructor(age: Int) { ... }
每个从构造方法由两部分组成。一部分是对其他构造方法的委托,另一部分是由花括号包裹的代码块。执行顺序上会先执行委托的方法,然后执行自身代码块的逻辑。
通过this关键字来调用要委托的构造方法。如果一个类存在主构造方法,那么每个从构造方法都要直接或间接地委托给它。比如,可以把从构造方法A委托给从构造方法B,再将从构造方法B委托给主构造方法。举个例子:
import org.joda.time.DateTime import org.joda.time.Years
class Bird(age: Int) { val age: Int init { this.age = age } constructor(timestamp: Long): this(DateTime(timestamp)) //构造函数A constructor(birth: DateTime): this(getAgeByBirth(birth)) //构造函数B }
fun getAgeByBirth(birth: DateTime): Int { return Years.yearsBetween(birth, DateTime.now()).years }
现在你应该对Kotlin中的主从构造方法有了一定的了解了。其实,从构造方法的设计除了解决我们以上的场景之外,还有一个很大的作用就是可以对某些Java的类库进行更好地扩展,因为我们经常要基于第三方Java库中的类,扩展自定义的构造方法。如果你从事过Android开发肯定了解,典型的例子就是定制业务中特殊的View类。比如以下的代码:
class KotlinView : View {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
super(context, attrs, defStyleAttr) {
...
}
}
可以看出,利用从构造方法,我们就能使用不同参数来初始化第三方类库中的类了。
- 点赞
- 收藏
- 关注作者
评论(0)