前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >转向Kotlin——对象

转向Kotlin——对象

作者头像
蜻蜓队长
发布2018-08-14 18:10:23
7380
发布2018-08-14 18:10:23
举报
文章被收录于专栏:Android机动车
由于Kotlin中没有静态成员的概念,因此Kotlin推出了一个有趣的语法糖:对象。那么对象能取代静态类成员吗?该怎么做呢?下面会详细介绍到。

对象表达式

在Java中又匿名类的概念,也就是说,在创建类的时候,无需指定类的名字。匿名类一般用于方法参数。基本理念就是方法需要接收一个类或者接口的实例,而这个实例只是在该方法中使用,没有必要单独再定义一个类,或者创建一个对象变量。因此,就在传入方法参数值的同时创建了该类的实例。代码例子如下:

代码语言:javascript
复制
public class JClass {

    public void fun(){
        System.out.println("jclass");
    }
}
代码语言:javascript
复制
public class JClassTest {

    public static void process(JClass jClass) {
        jClass.fun();
    }

    public static void main(String[] agrs) {
        process(new JClass() {
            @Override
            public void fun() {
                System.out.println("haha jclass");
            }
        });
    }

}

最终输出 haha jclass

在Kotlin中也有类似的功能,但不是匿名类,而是对象。与上面代码相同功能,下面是Kotlin代码:

代码语言:javascript
复制
object JClassTest {

    fun process(jClass: JClass) {
        jClass.`fun`()
    }

    @JvmStatic
    fun main(agrs: Array<String>) {
        process(object : JClass() {
            override fun `fun`() {
                println("haha jclass")
            }
        })
    }

}

可以看到,要想建立一个对象,就要使用object关键字,该对对象要继承的类需要与object之间用冒号(:)分隔。

对象和类一样,只能有一个父类,但可以实现多个接口,下面的代码中,对象不仅继承了JClass类,还实现了JInterface接口:

代码语言:javascript
复制
process(object : JClass(), JInterface {
    override fun printlnData() {
        println("haha jinterface")
    }

    override fun `fun`() {
        println("haha jclass")
    }
})

如果只想建立一个对象,不想继承任何类,也不想实现任何接口,可以按下面的方式建立:

代码语言:javascript
复制
var data = object {
    var value: String = "H"
}

声明匿名对象

匿名对象只能用在本地(函数)或private声明中。如果将匿名对象用于public函数的返回值,或者public属性的类型,那么Kotlin编译器会将这些函数或属性的返回类型重新定义为匿名对象的夫类型,如果匿名对象没有继承任何类,也没有实现任何接口,那么父类型就是Any。因此,添加在匿名对象中的任何成员都将无法访问。

代码语言:javascript
复制
class ObjectClass {
    // private函数,返回类型是匿名对象本身,可以访问x
    private fun foo() = object {
        var x = 1
    }

    // public函数,由于匿名对象没有任何父类型,因此函数的返回类型是Any
    public fun publicFoo() = object {
        var x = 2
    }

    fun bar() {
        var x = foo().x //可以访问
//        var x2 = publicFoo().x // 编译错误,publicFoo返回的是Any对象
    }
}

访问封闭作用域内的变量

在Java中,匿名对象访问封闭作用域内的变量,需要用final声明该变量,这也就意味着在匿名对象中无法修改封闭作用域内变量的值。在Java8中,如果只是使用封闭作用域内的变量,该比那辆无需使用final,但一旦修改变量的值,就必须使用final进行修饰,其实在Java8中,,封闭作用域的变量是一个隐式的final变量。

但是在Kotlin中,在匿名对象中就可以任意访问封闭作用域内的变量,包括修改它的值:

代码语言:javascript
复制
    fun main(agrs: Array<String>) {
        var n = 10
        process(object : JClass(), JInterface {
            override fun printlnData() {
                println("$n")
                println(n++)
            }
        })
    }

陪伴对象

在Kotlin中并没有静态类成员的概念,但并不等于不能实现类似于静态类成员的功能。陪伴对象就是Kotlin中用来解决这个问题的语法糖。

如果在Kotlin类中定义对象,那么就称这个对象为该类的陪伴对象。陪伴对象要使用companion关键字声明:

代码语言:javascript
复制
class CompanionClass {

    companion object {
        val TAG = "JIA"

        fun create(): CompanionClass = CompanionClass()
    }

}

陪伴对象中定义的成员是可以直接通过类名访问的。

代码语言:javascript
复制
var instance=CompanionClass.create()

注意,虽然陪伴对象的成员看起来很像其他语言中的类的静态成员,但在运行期间,这些成员任然是真实对象的实例的成员,它们与静态成员是不同的。不过使用@Jvmtatic进行注释,Kotlin编译器会将其编译成Byte Code真正的静态方法。这些内容以后会详细介绍。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android机动车 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 对象表达式
  • 声明匿名对象
  • 访问封闭作用域内的变量
  • 陪伴对象
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档