《Kotlin核心编程》 ——3.5 从static到object

举报
华章计算机 发表于 2020/02/21 23:09:26 2020/02/21
【摘要】 本节书摘来自华章计算机《Kotlin核心编程》 —— 书中第3章,第3.5.1节,作者是水滴技术团队 。

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中的单例模式。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。