IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Kotlin - 单例、伴生对象(静态)、匿名内部类 companion object -> 正文阅读

[移动开发]Kotlin - 单例、伴生对象(静态)、匿名内部类 companion object

对象声明(单例)

定义一个类并创建它的实例。可以继承类实现接口、包含属性和方法,但是不能手动声明构造。

?Kotlin声明:可以声明在顶层、也可以声明在类中(见下方和伴生对象对比)

object Demo{
    val name = "单例"
    fun show() = println(name)
}

Demo.show()
println(Demo.name)

反编译成Java代码:

public final class Demo {
    //成员变量
    private static String name;
    //通过静态字段提供实例
    public static final Demo INSTANCE;
    //私有化构造
    private Demo() { }
    //静态代码块中初始化
    static {
        Demo var0 = new Demo();
        INSTANCE = var0;
        name = "单例";
    }
    //成员方法
    public final void show() {
        String var1 = name;
        System.out.println(var1);
    }
    //生成的getter、setter
    public final String getName() { return name; }
    public final void setName(@NotNull String var1) {
        Intrinsics.checkNotNullParameter(var1, "<set-?>");
        name = var1;
    }
}

?模仿Java方式写Kotlin带参数单例:

class Demo private constructor(
    private var id: Long,
    private var name: String
) {
    companion object {
        private var instance: Demo? = null
        fun getInstance(id: Long, name: String) {
            instance ?: synchronized(this) {
                instance ?: Demo(id, name).also { instance = it }
            }
        }
    }
}

伴生对象(static静态、工厂模式)

  • 伴随着类而存在的对象,在类加载的时候初始化。Kotlin 中没有 static 静态的概念,可以使用顶层函数和常量。顶层函数不能访问类中私有的成员,在伴生对象中需要用外部实例来访问(静态内部类无法直接访问外部类中的非静态成员),Outter().num。
  • 当类中成员和伴生对象中成员重名的时候,类名调用的是伴生对象中的,实例调用的是类中的。

伴生对象

类中单例对象声明

相同

都是一个静态内部类,通过(外部类名.内部类名.成员名)的方式调用。

构造都是 private

都可以继承类、实现接口、拥有属性和函数

不同

①外部类中创建并持有伴生对象的实例

②定义的属性会成为外部类的私有静态字段,声明private便不会。函数还留在内部

③一个类中只能拥有一个伴生对象

①自己就是实例

②持有自己的属性和函数

③一个类中可以拥有多个单例对象

Kotlin声明:伴生对象和类中的单例

class Demo {
    //伴生对象
    companion object AA{    //不取名的话,默认名称是 Companion
        var a = 1
        fun aa() = println("伴生对象")
    }
    //单例
    object BB {
        var b = 2    //可以自定义getter、setter
        fun bb() = println("单例")
    }
}

?反编译成Java代码:

public final class Demo {
    //伴生对象中的成员变量(外部类持有)
    private static int a = 1;
    //持有伴生对象实例(外部类持有)
    public static final Demo.AA AA = new Demo.AA((DefaultConstructorMarker)null);
    
    //伴生对象
    public static final class AA {
        //私有化构造
        private AA() { }
        // $FF: synthetic method    合成的方法
        public AA(DefaultConstructorMarker $constructor_marker) {
            this();
        }
        //成员方法
        public final void aa() {
            String var1 = "伴生对象";
            System.out.println(var1);
        }
        //生成的getter、setter
        public final int getA() { return Demo.a; }
        public final void setA(int var1) { Demo.a = var1; }
    }
    
    //单例
    public static final class BB {
        //通过静态字段提供实例
        public static final Demo.BB INSTANCE;
        //私有化构造
        private BB() { }
        //静态代码块中初始化
        static {
            Demo.BB var0 = new Demo.BB();
            INSTANCE = var0;
            b = 2;
        }
        //成员变量
        private static int b;
        //成员方法
        public final void bb() {
            String var1 = "单例";
            System.out.println(var1);
        }
        //生成的getter、setter
        public final int getB() { return b; }
        public final void setB(int var1) { b = var1; }
    }

}

静态工厂:

interface Car {
    val brand: String
    companion object {
        operator fun invoke(type: CarType): Car {
            return when (type) {
                CarType.AUDI -> Audi()    
                CarType.BMW -> BMW()
            }
        }
    }
}

Car(CarType.BMW)

扩展方法:虽然是在伴生对象上扩展,实际相当于给外部类增加了静态方法。

fun Outter.Companion.show(){}
Outter.show()

对象表达式(匿名内部类)

不像 Java 的匿名内部类只能单继承/单实现,Kotlin 匿名对象可以一次搞定多个接口/抽象类,访问外部局部变量也不用加 final。一般使用 Lambda 更便捷,当需要重写多个方法时,只能选择匿名对象了。

xxx.setOnClickListener(object : View.OnClickListener{
    override fun onClick(v: View){...}
})

xxx.setOnClickListener{ view -> ... }
interface AA{ fun aa() }
interface BB{ fun bb() }
fun method(param:AA){ param.aa() }
//调用
method(object : AA,BB {
    override fun aa() {...}
    override fun bb() {...}
})
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-19 11:59:56  更:2022-05-19 12:00:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:39:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码