《Kotlin核心编程》 ——3.5 从static到object
3.5 从static到object
阅读本书到现在,你肯定发现了一个有趣的现象—没有任何一段Kotlin代码中出现过static这个关键字。在Java中,static是非常重要的特性,它可以用来修饰类、方法或属性。然而,static修饰的内容都是属于类的,而不是某个具体对象的,但在定义时却与普通的变量和方法混杂在一起,显得格格不入。
在Kotlin中,你将告别static这种语法,因为它引入了全新的关键字object,可以完美地代替使用static的所有场景。当然除了代替使用static的场景之外,它还能实现更多的功能,比如单例对象及简化匿名表达式等。
3.5.1 什么是伴生对象
按照规则,先来看一个可比较的Java例子:
public class Prize {
private String name;
private int count;
private int type;
public Prize(String name, int count, int type) {
this.name = name;
this.count = count;
this.type = type;
}
static int TYPE_REDPACK = 0;
static int TYPE_COUPON = 1;
static boolean isRedpack(Prize prize) {
return prize.type == TYPE_REDPACK;
}
public static void main(String[] args) {
Prize prize = new Prize("红包", 10, Prize.TYPE_REDPACK);
System.out.println(Prize.isRedpack(prize));
}
}
这是很常见的Java代码,也许你已经习惯了。但是如果仔细思考,会发现这种语法其实并不是非常好。因为在一个类中既有静态变量、静态方法,也有普通变量、普通方法的声明。然而,静态变量和静态方法是属于一个类的,普通变量、普通方法是属于一个具体对象的。虽然有static作为区分,然而在代码结构上职能并不是区分得很清晰。
那么,有没有一种方式能将这两部分代码清晰地分开,但又不失语义化呢?Kotlin中引入了伴生对象的概念,简单来说,这是一种利用companion object两个关键字创造的语法。
伴生对象
顾名思义,“伴生”是相较于一个类而言的,意为伴随某个类的对象,它属于这个类所有,因此伴生对象跟Java中static修饰效果性质一样,全局只有一个单例。它需要声明在类的内部,在类被装载时会被初始化。
现在我们就来改写一个伴生对象的版本:
class Prize(val name: String, val count: Int, val type: Int) {
companion object {
val TYPE_REDPACK = 0
val TYPE_COUPON = 1
fun isRedpack(prize: Prize): Boolean {
return prize.type == TYPE_REDPACK
}
}
}
fun main(args: Array<String>) {
val prize = Prize("红包", 10, Prize.TYPE_REDPACK)
print(Prize.isRedpack(prize))
}
可以发现,该版本在语义上更清晰了。而且,companion object用花括号包裹了所有静态属性和方法,使得它可以与Prize类的普通方法和属性清晰地区分开来。最后,我们可以使用点号来对一个类的静态的成员进行调用。
伴生对象的另一个作用是可以实现工厂方法模式。我们在前面讲解过如何使用从构造方法实现工厂方法模式,然而这种方式存在以下缺点:
利用多个构造方法语意不够明确,只能靠参数区分。
每次获取对象时都需要重新创建对象。
你会发现,伴生对象也是实现工厂方法模式的另一种思路,可以改进以上的两个问题。
class Prize private constructor(val name: String, val count: Int, val type: Int) {
companion object {
val TYPE_COMMON = 1
val TYPE_REDPACK = 2
val TYPE_COUPON = 3
val defaultCommonPrize = Prize("普通奖品", 10, Prize.TYPE_COMMON)
fun newRedpackPrize(name: String, count: Int) = Prize(name, count, Prize.TYPE_REDPACK)
fun newCouponPrize(name: String, count: Int) = Prize(name, count, Prize.TYPE_COUPON)
fun defaultCommonPrize() = defaultCommonPrize //无须构造新对象
}
}
fun main(args: Array<String>) {
val redpackPrize = Prize.newRedpackPrize("红包", 10)
val couponPrize = Prize.newCouponPrize("十元代金券", 10)
val commonPrize = Prize.defaultCommonPrize()
}
总的来说,伴生对象是Kotlin中用来代替static关键字的一种方式,任何在Java类内部用static定义的内容都可以用Kotlin中的伴生对象来实现。然而,它们是类似的,一个类的伴生对象跟一个静态类一样,全局只能有一个。这让我们联想到了什么?没错,就是单例对象,下面我们会介绍如何用object更优雅地实现Java中的单例模式。
- 点赞
- 收藏
- 关注作者
评论(0)