Object Expressions and Declarations

对象表达式和申明:
    有些时候我们需要创建一个轻量修改的类,没有明确申明一个新的超类,Java处理这种情况是用一个异步内部类实现,kotlin则用对象表达式和对象申明的概念来实现。
    
    对象表达式:
        创建一个继承某些类的异步类对象,我们这样写:
        
```
window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
        // ...
    }

    override fun mouseEntered(e: MouseEvent) {
        // ...
    }
})
```
如果超类有一个构造函数,那么必须传递一个合适构造参数,某些超类应该在冒号之后写成为一个逗号分开的列表
```
open class A(x: Int) {
    public open val y: Int = x
}

interface B {...}

val ab: A = object : A(1), B {
    override val y = 15
}
```
如果,某些情况下,我们需要仅仅一个对象,没有复杂的超类,我们可以简单的写成这样:
```
fun foo() {
    val adHoc = object {
        var x: Int = 0
        var y: Int = 0
    }
    print(adHoc.x + adHoc.y)
}
```
这个有点像Java中的匿名类,并把索引给参数adHoc,里面定义了两个属性值,通过.操作进行取值。

注意:异步对象可以在仅仅是一个本地私有申明的时候用来做当作一个类,如果你使用一个异步对象作为公共函数返回值的类型或者公共属性的返回类型,那么这个实际类型
式函数或者属性将被申明这个异步对象的超类或者返回Any,如果你没有申明任何超类,添加在异步对象的成员将不可被访问
```
class C {
    // Private function, so the return type is the anonymous object type
    private fun foo() = object {
        val x: String = "x"
    }

    // Public function, so the return type is Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    fun bar() {
        val x1 = foo().x        // Works
        val x2 = publicFoo().x  // ERROR: Unresolved reference 'x'
    }
}
```
仅仅想Java的异步内部类,代码在对象表达式中可以访问外部块(不像java,这没有限制为final变量)
```
fun countClicks(window: JComponent) {
    var clickCount = 0
    var enterCount = 0

    window.addMouseListener(object : MouseAdapter() {
        override fun mouseClicked(e: MouseEvent) {
            clickCount++
        }

        override fun mouseEntered(e: MouseEvent) {
            enterCount++
        }
    })
    // ...
}
```
    对象申明:
    
    单例模式是一个非常有用的模式,并且Kotlin可以很容易把他申明单例模式,
```
object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
        // ...
    }

    val allDataProviders: Collection<DataProvider>
        get() = // ...
}
```
这个叫做对象申明,并且他总是有一个object关键词在名字后面。仅仅像一个变量申明,一个对象申明不是一个表达式,没有可能被用到在约定申明的右手边,联系到对象,我们直接用他的名字
```
DataProviderManager.registerDataProvider(...)
```
如此对象拥有超类
```
object DefaultListener : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
        // ...
    }

    override fun mouseEntered(e: MouseEvent) {
        // ...
    }
}
```
标记:对象申明没有本地,但是他们可以嵌套进其他对象申明或者非内部类


同伴对象:
    在类中的对象申明可以用companion标记
```
class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}
```
同伴对象的成员可以被调用通过使用简单的类名字当做修饰
```
val instance = MyClass.create()
```
同伴对象的名字可以被省略,在Companion将被使用的例子中
```
class MyClass {
    companion object {
    }
}

val x = MyClass.Companion
```
记录:即使同伴对象的成员看起来像静态成员,在运行时,这些真实对象的陈成员仍然存在,并且可能比如继承接口,:
```
interface Factory<T> {
    fun create(): T
}


class MyClass {
    companion object : Factory<MyClass> {
        override fun create(): MyClass = MyClass()
    }
}
```
然而在JVM中你可以拥有同伴对象的成员当做静态方法和域生产。如果你使用@JvmtSatic,[Java interoperability](http://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#static-fields)

在对象表达式和申明中的语义区别:
这有一个重点语义区别:
    1、对象表达式可以在需要使用的时候被立即执行
    2、对象申明在我们第一次访问的时候进行延迟申明
    3、一个同伴对象当当前类被加载被初始化,匹配的是Java静态初始化语义

转载于:https://my.oschina.net/u/195533/blog/905462

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值