当前位置:嗨网首页>书籍在线阅读

02-对象表达式

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

9.1.1 对象表达式

在Java中,匿名类是一个很重要的概念。创建匿名类时无须指定类名,因为没有名称,所以匿名类不可以声明对象,但可以创建对象。匿名类主要在方法的参数类型中使用,当类中的方法或属性不需要被重复利用时,匿名类是一种合适的选择。

public class Test {
     public static void main(String[] args) {
          //创建匿名类
        Speak speak = new Speak() {
            @Override
            public void say() {
              System.out.println("hello word");
            }
        };
        speak.say();
    }
}
interface Speak {
    void say();
}

当子类的类体比较简单时,也可以考虑使用匿名类,匿名类一定是内部类,而且可以访问外嵌类的成员变量和方法。

Kotlin也提供了类似的功能,但不是匿名类,而是对象。要创建一个对象,需要使用关键字object,该对象和继承的匿名类对象之间使用冒号分隔,冒号用来表示继承关系。对于上面的Java代码,转化为Kotlin代码如下。

fun main(args: Array<String>) {
    val speak = object : Speak {
        override fun say() {
            println("hello word")
        }
    }
    speak.say()
}
internal interface Speak {
    fun say()
}

如果超类中有一个构造函数,则必须传递适当的参数给构造函数,当出现多个超类时,可以由跟在冒号后面的逗号分隔列表。代码如下。

fun main(args: Array<String>) {
    val ab: A = object : A(1), B {
        override val y = 15
    }
}
interface B {
    //…
}
open class A(x: Int) {
     open val y: Int = x
}

如果只需要建立一个对象,而不想从任何类继承,也不想实现任何接口,那么可以按照下面的方式建立对象。

fun foo() {
   //建立一个对象,该对象没有任何父类型
    val adHoc = object {
        var x: Int = 0
        var y: Int = 0
    }
    print(adHoc.x + adHoc.y)
}

匿名对象可以作用于本地和私有域中声明的类型,如果使用匿名对象作为公有函数的返回类型或者公有属性的类型,那么该函数或属性的实际类型是匿名对象声明的超类型;如果没有声明任何超类型,则默认为Any类型。代码如下。

class C {
    // 私有函数,返回类型是匿名对象类型
    private fun foo() = object {
        val x: String = "x"
    }
    // 公有函数,返回类型是Any
    fun publicFoo() = object {
        val x: String = "x"
    }
    fun bar() {
        val x1 = foo().x        // 编译正确
        val x2 = publicFoo().x  // 编译错误,不能解析引用“x”
    }
}

与Java的匿名内部类一样,Kotlin的对象表达式代码可以访问包含它的作用域变量,而不仅限于final类型的变量。