object关键字在多种情况下出现,其核心理念:将声明一个类和创建一个实例结合起来。class
使用场景:
1、对象声明是定义单例的一种方式。
2、伴生对象可以持有工厂方法和其他与这个类有关。但在调用时并不依赖类实例的方法。他们的成员可以通过类名来访问。
3、对象表达式用来代替Java的匿名内部类。
1.1、对象声明:创建单例易如反掌
Kotlin通过使用对象声明功能将类的声明与该类的单一实例声明结合到了一起。
object Payroll{
val allEmployees=arrayListOf<Person>()
fun calculateSalary(){
for(person in allEmployees){...}
}
}
对象声明唯一不允许的就是构造方法,包括朱构造方法和从构造方法。
调用:Payroll.allEmployees.add(Person(...))
Payroll.calculateSalary()
对象声明同样可以继承自类和接口。通常在你使用的框架需要趋势线一个接口,但是你的实现并不包含任何状态的时候很有用。例如Comparator接口。
1.2、伴生对象:工厂方法和静态成员的地盘
Kotlin中的类不能拥有静态成员,它没有static关键字。包级别函数(多顶层函数) 可以替代 Java静态的方法 ;对象声明 可以替代 Java静态方法 和 静态字段。顶层函数不能访问类的private成员,可以使用 那个类中的对象声明的成员。
在类中定义的对象之一可以使用一个特殊的关键字来标记:companion 。这样可以直接通过容器类名称来访问这个对象的方法和属性。
class A {
companion object {
fun bar() = println(" Companion object called ")
}
}
调用:A.bar()
class User { //一般我们会用多个构造来创建不同的对象
val nickname : String
constructor(email:String){
nickname=email.substringBefore('@')
}
constructor(facebookAccountId:Int){
nickname=getFacebookName(facebookAccountId)
}
private fun getFacebookName(facebookAccountId: Int): String {
return "facebookUserName"
}
}
//使用工厂方法来代替从构造方法
class Userprivate constructor(val nickname : String){
private val niname ="bob" // 在companion object 内无法访问
companion object {
fun newSubscribingUser(email: String) = User(email.substringBefore('@'))
fun newFacebookUser(accountId : Int) = User(getFacebookName(accountId))
private fun getFacebookName(accountId: Int): String {
return "facebookUserName"
}
}
}
优点:工厂方法可以返回声明这个方法的类的子类(如newSubscribingUser,newFacebookUser类都是User的子类)
缺点:如果要扩展这样的类,使用多构造方法更好,因为伴生对象成员在子类中不能被重写。
1.3、作为普通对象使用的伴生对象
1.3.1、声明一个命名伴生对象
class Person(val name :String){
companion object Loader{ //声明一个命名伴生对象
fun fromJson(jsonText:String):Person = Person(jsonText)
}
}
1.3.2、在伴生对象中实现接口
interface JSONFactory{
fun fromJSON(jsonText: String):T
}
class Person(val name :String){
companion object : JSONFactory{
override fun fromJSON(jsonText: String): Person { //实现接口的伴生对象
return Person(jsonText)
}
}
}
1.3.3、伴生对象的扩展
class Person(val firstName : String,val lastName :String){
companion object { //空的伴生对象
}
}
fun Person.Companion.fromJson(json;String) :Person{} //声明扩展函数
val p=Person.fromJson(json) //调用
1.4、对象表达式:改变写法的匿名内部类
object关键字还可以用来声明匿名对象。
window.addMouseListener (
object:MouseAdapter(){ //声明继承MouseAdapter的匿名对象
override fun mouseClicked(e:MouseEvent){}
override fun mouseEntered(e:MouseEvent){}
}
)
与对象声明不同,匿名对象不是单例的。每次对象表达式被执行都会创建一个新的对象实例。
扩展函数我的通俗理解:类名.方法名 的方法 称之为扩展函数。
fun countClicks(window:Window){
var clickCount= 0
window.addMouseListener(
object:MouseAdapter(){ //声明继承MouseAdapter的匿名对象
override fun mouseClicked(e:MouseEvent){clickCount ++ } //匿名对象访问局部变量
override fun mouseEntered(e:MouseEvent){}
}
)
}
网友评论