常量声明和伴生对象的使用是Kotlin中的重要概念,它们取代了Java中的静态成员以及与之相关的在面向对象编程(OOP)和函数式编程之间交叉时的困难。
问题的历史: 在Java中,常量通常使用static final字段,静态方法用于辅助或工厂功能。在Kotlin中,static被替换为object和companion object,而对于编译时常量则使用关键词const。
问题: 需要声明不依赖于类实例的值,并组织工厂方法和静态状态,而不破坏OOP的完整性。
解决方案: 伴生对象(companion object)在类内部声明,允许放置对所有实例共同的成员:
代码示例:
class MyClass { companion object { const val DEFAULT_LIMIT = 10 fun create(): MyClass = MyClass() } } val limit = MyClass.DEFAULT_LIMIT val instance = MyClass.create()
关键特点:
伴生对象可以在类中有多个实例吗?
不可以,一个类中只能有一个伴生对象。尝试声明第二个将导致编译错误。但是,在伴生对象内可以有任意数量的方法/属性。
可以在伴生对象内部初始化lateinit变量吗?
不可以,因为带有const的属性或伴生对象内的变量必须立即初始化,或者是带有显式初始化的val/var。伴生对象内部不允许使用lateinit。
伴生对象可以有自己的名称吗?何时需要?
可以,伴生对象的名称是显式指定的,如果需要通过名称访问它或者实现接口时。例如:
class Foo { companion object Factory { fun create(): Foo = Foo() } } val instance = Foo.Factory.create()
程序的所有辅助功能和全局变量都放在伴生对象中,使用var而不是val/const:
优点:
缺点:
仅在伴生对象内使用编译时常量(const val)和纯函数,所有可变的要么是局部的,要么通过依赖注入传递:
优点:
缺点: