
匿名类
定义
在 Kotlin 中,“匿名类”指的是没有显式名称的类定义,通常是通过对象表达式(object expression) 来创建的一个对象实例。
💡 简单理解:匿名类 = 定义一个临时类 + 立即实例化一个对象。
匿名类在 Kotlin 中通过对象表达式(Object Expression) 来实现
val obj = object {
val x = 10
fun show() = println("x = $x")
override fun toString(): String = "我是一个匿名类" // 匿名类默认继承于Any,可以直接重写其toString
}
obj.show() // 输出:x = 10
println(obj) //
这里的 object { ... } 创建了一个没有名字的类,并立即实例化。
可以在匿名类中定义:
- 属性(
val、var) - 方法
- 初始化块(
init)
val obj = object {
val name = "Kotlin"
init {
println("Initializing $name")
}
fun greet() = println("Hello, $name!")
}
obj.greet()
// Initializing Kotlin
// Hello, Kotlin!
匿名类不仅可以直接定义,也可以继承某个类,或实现某个接口:
interface Person {
fun chat()
}
open class Human(val name: String)
fun main() {
val obj: Human = object : Human("小明"), Person { // 继承类时,同样需要调用其构造函数
override fun toString() = "我叫$name" // 使用父类的属性
}
println(obj)
}
继承抽象类
abstract class A {
abstract fun greet()
}
interface B {
fun sayBye()
}
val obj = object : A(), B {
override fun greet() = println("Hi!")
override fun sayBye() = println("Bye!")
}
obj.greet()
obj.sayBye()
像这样,之前无法实例化的接口或抽象类,可以通过匿名类的形式得到一个实例化对象。
为什么需要匿名类
匿名类存在的主要目的是:
- 临时创建对象(例如:事件监听器、回调函数、一次性使用的对象)
- 扩展已有类或实现接口而不需要额外定义类名
- 实现抽象类或接口的匿名实现
匿名类不能声明构造函数(因为没有类名可供定义构造函数)
但是可以调用父类构造函数
open class Base(val msg: String)
val obj = object : Base("Hello") {
fun show() = println(msg)
}
obj.show() // Hello
匿名类与函数式接口(SAM 接口)
函数式接口(Functional Interface)是指只包含一个抽象方法的接口,但可以有多个非抽象成员(default、static 方法)、多个常量属性
在 Kotlin 中用 fun interface 关键字声明:
fun interface ClickListener {
fun onClick()
}
匿名类实现函数式接口
// 传统方式
val listener = object : ClickListener {
override fun onClick() {
println("Clicked!")
}
}
// Lambda 简化
val listener = ClickListener { println("Clicked!") }
listener.onClick()
这种写法称为 SAM 转换(Single Abstract Method conversion),Kotlin 会自动将 Lambda 转换为该接口的匿名类实例。
函数式接口对象作为函数参数
fun interface Printer {
fun print()
}
fun test(printer: Printer) {
printer.print()
}
// 调用
test { // Lambda
println("Hello World")
}
匿名类的作用域与类型
如果匿名对象被赋值给一个具有显式类型的变量,那么编译器只知道它的父类型:
interface A { fun show() }
val a: A = object : A {
val x = 10
override fun show() = println("x=$x")
}
a.show() // ✅ 可调用
// println(a.x) // ❌ 无法访问,因为类型是 A,而不是匿名类型
如果没有显式类型,Kotlin 会保留匿名类的真实类型信息:
val a = object : A { // 这里a类型:<anonymous object : A>
val x = 10
override fun show() = println("x=$x")
}
println(a.x) // ✅ 可调用
函数返回匿名类对象同样
open class Human(val name: String)
fun test() = object: Human("小明") {
val age: Int = 10
override fun toString() = "我叫$name"
}
val human1 = test() // 这里human1类型:<anonymous object : Human>
println(human1.name)
println(human1.age)
val human2: Human = test()
println(human1.name)
println(human1.age) // 编译错误
单例类
单例(Singleton)指一个类在整个程序运行过程中只有一个实例(对象),并且提供一个全局访问点。
在许多情况下,我们只希望某个类存在唯一的实例,例如:
- 管理全局配置(如
ConfigManager) - 管理数据库连接(
DatabaseHelper) - 管理日志输出(
Logger) - 管理网络请求队列(
NetworkManager)
在 Java 中,通常需要写很多代码来实现单例,而在 Kotlin 中,只需要用一个关键字:object
object Singleton {
private var count = 0
fun showCount() {
println("Count = $count")
}
fun addCount() {
count += 1
}
override fun toString() = "count——$count"
}
fun main() {
Singleton.count++ // 编译错误,private
Singleton.addCount() // 单例定义的函数直接使用类名即可调用
Singleton.showCount() // Count = 1
val a = Singleton // 通过类名直接得到此单例类的对象
val b = Singleton
val c = Singleton() // 编译错误,不可以通过构造函数的形式创建对象
println(a === b) // true,说明 a 和 b 是同一个对象
a.showCount() // 不推荐
println(a) // count——1
}
伴生对象
伴生对象(companion object)是类内部的一个对象,它允许我们在类内部声明一些类似 Java 静态成员的属性和方法。
在 Kotlin 中没有 static 关键字,伴生对象就是 Kotlin 对应的静态成员实现方式。
class MyClass {
companion object {
val CONSTANT = 100
fun greet() = println("Hello from companion object")
}
}
fun main() {
println(MyClass.CONSTANT) // 100
MyClass.greet() // Hello from companion object
}
也可以给伴生对象起名字
class MyClass {
companion object Factory {
fun create() = MyClass()
}
}
val obj = MyClass.create() // 使用名字也可以 MyClass.Factory.create()
可以在伴生对象中定义静态工厂方法来创建类实例。
class User private constructor(val name: String) {
companion object {
fun create(name: String): User = User(name)
}
}
fun main() {
val user = User.create("Alice")
println(user.name) // Alice
}
伴生对象可以实现接口
interface Factory<T> {
fun create(): T
}
class Product {
companion object : Factory<Product> {
override fun create(): Product = Product()
}
}
伴生对象是单例
每个类只会有一个伴生对象实例,伴生对象实例在第一次访问类时被初始化(lazy)。
class Example {
companion object {
init { println("Companion object initialized") }
}
}
fun main() {
println("Before accessing")
Example // 还没访问 companion
println("After accessing")
}
/*
Before accessing
Companion object initialized
After accessing
*/
通过 @JvmStatic 注解生成 Java 风格静态方法,以便 Java 代码调用
class MyClass {
companion object {
@JvmStatic
fun staticMethod() = println("Java static style")
}
}
1677

被折叠的 条评论
为什么被折叠?



