住建房产信息查询,免费关键词排名优化软件,俄罗斯最新军事动态,抖音小程序怎么入驻前言
本文主要讲解kotlin对象和委托。 Kotlin文章列表
Kotlin文章列表: 点击此处跳转查看 目录 1.1 对象
在Kotlin中#xff0c;对象#xff08;Object#xff09;是一个具有特殊用途的单例实例。它是一种创建单个实例的方式#xff0c;确保在整个应用程序中只存在一个特…前言
本文主要讲解kotlin对象和委托。 Kotlin文章列表
Kotlin文章列表: 点击此处跳转查看 目录 1.1 对象
在Kotlin中对象Object是一个具有特殊用途的单例实例。它是一种创建单个实例的方式确保在整个应用程序中只存在一个特定对象。
对象在Kotlin中有以下特点和用途
单例实例对象只能有一个实例这意味着在整个应用程序中只能使用同一个对象。属性和方法对象可以具有属性和方法可以通过对象名称直接访问它们。延迟初始化对象的初始化是惰性的即只有在第一次访问时才会被实例化。替代类对象可以用来替代传统的类实例尤其是对于一些简单的场景。
在生活中我们可以以公司为例来解释对象的概念。假设我们有一个名为Company的对象它代表了一个公司。该对象可能具有属性如公司名称、地址等还可能具有方法如招聘员工、发布公告等。由于一个公司在整个应用程序中应该是唯一的我们可以使用对象来表示这个公司以确保只有一个实例存在。
下面是使用步骤、原理、底层实现、优缺点、注意事项和应用场景的详细解释
使用步骤 创建对象使用object关键字创建一个对象并指定其名称。定义属性和方法在对象内部定义需要的属性和方法。使用对象通过对象名称直接访问属性和方法。 原理和底层实现 对象是通过静态初始化器实现的确保在首次访问时进行实例化。Kotlin编译器会生成一个与对象名称相同的类该类具有静态字段和静态方法。对象在内部使用了线程安全的双重校验锁定Double-checked locking来实现延迟初始化和保证线程安全。 优点 简单易用使用对象可以避免手动实现单例模式的繁琐过程。延迟初始化对象在第一次访问时才会被初始化避免了不必要的开销。线程安全对象的实例化使用双重校验锁定保证了线程安全。 缺点和注意事项 对象的状态是全局的可能会引起状态共享和数据竞争的问题需要小心处理。对象的生命周期与应用程序相同不能手动销毁。 应用场景 单例模式当需要保证全局只有一个实例时可以使用对象来实现单例模式。工具类当有一组相关的方法需要在整个应用程序中使用时可以将这些方法放在一个对象中。配置信息当需要在应用程序中共享配置信息时可以使用对象来保存配置数据。
下面是一个具体案例的完整Kotlin代码使用对象来表示一个公司并实现一些基本的功能
// 定义一个Company对象
object Company {var name: String var address: String fun hireEmployee(name: String) {println($name has been hired by $name)}fun postAnnouncement(announcement: String) {println(Announcement: $announcement)}
}fun main() {// 使用Company对象Company.name ABC CompanyCompany.address 123 Main Streetprintln(Company Name: ${Company.name})println(Company Address: ${Company.address})Company.hireEmployee(John Doe)Company.postAnnouncement(Welcome to our company!)// 对象的实例化是延迟的这里才会初始化val companyName Company.nameprintln(Stored Company Name: $companyName)
}运行结果
Company Name: ABC Company
Company Address: 123 Main Street
John Doe has been hired by John Doe
Announcement: Welcome to our company!
Stored Company Name: ABC Company在上述示例中我们创建了一个名为Company的对象并定义了name、address属性和hireEmployee、postAnnouncement方法。在main函数中我们使用Company对象来设置公司的名称和地址并调用对象的方法来雇佣员工和发布公告。最后我们还演示了对象的延迟初始化特性将公司名称存储到一个变量中并进行打印输出。 1.1.1 对象表达式
在Kotlin中对象表达式Object Expression是一种在使用时创建匿名对象的方式。与对象声明不同对象表达式用于创建临时的、只在特定上下文中使用的对象。
对象表达式具有以下特点和用途
匿名对象对象表达式创建的对象没有显式的名称只能通过变量引用来使用。局部性对象表达式在创建时绑定到特定的上下文并且只在该上下文中有效。可继承性对象表达式可以实现接口或继承类并可以重写其方法。替代类的实例对象表达式可以用作替代传统类实例的简洁方式。
下面是使用步骤、原理、底层实现、优缺点、注意事项和应用场景的详细解释
使用步骤 创建对象表达式使用object关键字创建一个对象表达式并定义其属性和方法。使用对象表达式对象表达式创建的对象可以通过变量引用来使用。 原理和底层实现 对象表达式在底层会被编译成一个匿名类。Kotlin编译器会为对象表达式生成一个匿名类并在需要时实例化该类。 优点 简洁对象表达式提供了一种快速创建临时对象的方式避免了显式定义类的过程。灵活性对象表达式可以在需要时实现接口或继承类具有更大的灵活性。 缺点和注意事项 对象表达式创建的对象只在特定的上下文中有效不能在其他地方复用。对象表达式通常用于创建临时对象不适合长期存储或共享状态。 应用场景 创建事件监听器在需要临时的事件监听器时可以使用对象表达式来快速创建一个匿名对象并实现事件处理逻辑。定义匿名类的实例当需要为特定接口或类创建一个简单的实现时可以使用对象表达式来创建匿名类的实例。
下面是一个具体案例的完整Kotlin代码演示了对象表达式的使用
// 定义一个接口
interface Greeting {fun greet()
}fun main() {// 使用对象表达式创建一个实现Greeting接口的匿名对象val englishGreeting object : Greeting {override fun greet() {println(Hello!)}}// 使用对象表达式创建一个实现Greeting接口的匿名对象val frenchGreeting object : Greeting {override fun greet() {println(Bonjour!)}}// 调用匿名对象的方法englishGreeting.greet()frenchGreeting.greet()
}运行结果
Hello!
Bonjour!在上述示例中我们定义了一个Greeting接口它包含了一个greet()方法。然后我们使用对象表达式创建了两个匿名对象分别实现了Greeting接口并重写了其中的greet()方法。我们创建了englishGreeting和frenchGreeting两个对象来表示英语和法语的问候语。最后我们通过调用匿名对象的greet()方法来输出问候语。请注意这些对象是临时创建的仅在特定的上下文中有效。 1.1.2 声明匿名对象
在 Kotlin 中你可以使用匿名对象Anonymous Object来创建一个没有任何命名标识符的对象通常用于实现某个接口或继承某个类的实例。匿名对象在一些特定的场景中很有用例如需要创建一个临时对象或者在某个函数内部创建一个对象而不必在全局范围内命名这个对象。
使用匿名对象的语法如下
实现接口的匿名对象
val interfaceInstance: SomeInterface object : SomeInterface {override fun someFunction() {// 实现接口中的函数}
}继承类的匿名对象
val superClassInstance: SomeSuperClass object : SomeSuperClass() {override fun someFunction() {// 重写继承类中的函数}
}匿名对象创建后你可以像普通对象一样使用它但是由于没有命名标识符无法在其他地方引用这个对象。因此匿名对象主要用于那些只需要在局部范围内使用的临时对象。
下面是一个完整的示例
interface SomeInterface {fun someFunction()
}open class SomeSuperClass {open fun someFunction() {println(SomeSuperClass: someFunction())}
}fun main() {// 匿名对象实现接口val interfaceInstance: SomeInterface object : SomeInterface {override fun someFunction() {println(Interface implementation: someFunction())}}interfaceInstance.someFunction()// 匿名对象继承类val superClassInstance: SomeSuperClass object : SomeSuperClass() {override fun someFunction() {super.someFunction() // 调用父类的函数println(Subclass implementation: someFunction())}}superClassInstance.someFunction()
}在上面的示例中我们通过匿名对象分别实现了 SomeInterface 接口和继承了 SomeSuperClass 类并对其中的函数进行了相应的实现。 1.1.3 访问封闭作用域内的变量
在Kotlin中可以通过对象表达式或Lambda表达式来访问封闭作用域Enclosing Scope内的变量。这允许在嵌套函数或Lambda函数中访问包含它们的函数或作用域中的变量。
下面是使用对象表达式和Lambda表达式访问封闭作用域内变量的示例代码
fun main() {val outerVariable Hello// 使用对象表达式访问封闭作用域内的变量val objectExpression object {fun printOuterVariable() {println(outerVariable)}}objectExpression.printOuterVariable()// 使用Lambda表达式访问封闭作用域内的变量val lambda {println(outerVariable)}lambda()
}运行结果
Hello
Hello在上述示例中我们定义了一个main函数并在函数内部声明了一个outerVariable变量。然后我们使用对象表达式创建了一个匿名对象其中定义了一个printOuterVariable方法该方法可以访问外部的outerVariable变量。通过调用对象表达式中的方法我们可以访问封闭作用域内的outerVariable变量。
接下来我们使用Lambda表达式创建了一个匿名函数其中输出了外部的outerVariable变量。通过调用Lambda函数我们同样可以访问封闭作用域内的outerVariable变量。
无论是对象表达式还是Lambda表达式它们都允许在嵌套函数或Lambda函数中访问封闭作用域内的变量。这种特性非常有用可以在需要时方便地访问外部作用域中的变量。 1.1.4 陪伴对象
在Kotlin中陪伴对象Companion Object是指在类内部定义的一个特殊对象它与类相关联并且可以访问类的私有成员。陪伴对象类似于Java中的静态成员但在Kotlin中更加灵活和功能丰富。
陪伴对象具有以下特点和用途
类关联陪伴对象与其所在的类相关联可以访问类的私有成员。类级别陪伴对象在类级别上存在可以拥有自己的属性和方法。命名每个类只能有一个陪伴对象并且可以通过Companion关键字访问。扩展功能陪伴对象可以扩展类的功能类似于扩展函数。
下面是使用步骤、原理、底层实现、优缺点、注意事项和应用场景的详细解释
使用步骤 在类内部定义陪伴对象使用companion object关键字在类内部定义一个陪伴对象。访问陪伴对象通过类名直接访问陪伴对象中的属性和方法。 原理和底层实现 陪伴对象在底层被编译为一个普通的类对象与类相关联并通过类名进行访问。陪伴对象内部的属性和方法在编译时会被转换为静态成员与类的实例无关。 优点 访问私有成员陪伴对象可以访问其所在类的私有成员方便地组织和访问相关逻辑。扩展功能陪伴对象可以添加类级别的属性和方法为类提供额外的功能。代码组织陪伴对象可以将相关的代码组织在一起提高代码的可读性和可维护性。 缺点和注意事项 陪伴对象的属性和方法在编译时会被转换为静态成员因此无法访问类的实例成员。陪伴对象的属性和方法不能被继承或覆盖。 应用场景 工厂方法陪伴对象可以提供类似于工厂方法的功能用于创建类的实例。静态常量陪伴对象可以定义类的静态常量例如数据库表名、文件路径等。工具类陪伴对象可以用于定义类的工具方法提供便捷的操作和功能。
下面是一个具体案例的完整Kotlin代码演示了陪伴对象的使用
class MyClass {companion object {private const val PREFIX MyClass:fun createInstance(): MyClass {println($PREFIX Creating an instance of MyClass)return MyClass()}}fun printMessage() {println($PREFIX Printing a message from MyClass)}
}fun main() {val obj MyClass.createInstance()obj.printMessage()
}运行结果
MyClass: Creating an instance of MyClass
MyClass: Printing a message from MyClass在上述示例中我们定义了一个名为MyClass的类并在其内部定义了一个陪伴对象。陪伴对象通过companion object关键字声明其中定义了一个createInstance()方法用于创建MyClass的实例。此外陪伴对象还定义了一个私有的常量PREFIX用于辅助打印信息。
在main函数中我们通过类名直接调用陪伴对象中的createInstance()方法来创建MyClass的实例。然后我们调用实例的printMessage()方法输出一个来自MyClass的消息。
通过使用陪伴对象我们可以在类内部组织和访问相关的属性和方法同时提供类级别的功能。陪伴对象允许我们在类的上下文中使用静态属性和方法的灵活性。 1.1.5 kotlin对象在Android中的使用
在 Kotlin 中对象Object是一种用来定义单例对象的特殊类。在 Android 开发中单例对象常用于实现全局共享的数据、资源、管理器等因为它们在应用程序的整个生命周期内只会被实例化一次。
使用 Kotlin 对象的语法很简单只需使用 object 关键字定义即可。下面是在 Android 中使用 Kotlin 对象的几个常见用例
1. 单例对象 单例对象可以用于全局共享数据或管理器确保整个应用程序只有一个实例。
object DataManager {// 在这里实现全局共享的数据或方法var sharedData: String fun doSomething() {// 实现某些操作}
}在任何地方你都可以直接访问 DataManager.sharedData 或者调用 DataManager.doSomething() 来使用这个单例对象。
2. 对象表达式 对象表达式允许你在需要时创建一个临时的对象通常用于实现某个接口或继承某个类的情况。这在处理回调、监听器等场景时很有用。
interface OnItemClickListener {fun onItemClick(item: String)
}class MyAdapter(private val listener: OnItemClickListener) {// 一些其他实现
}// 在使用 MyAdapter 的地方可以创建一个匿名的 OnItemClickListener 对象
val adapter MyAdapter(object : OnItemClickListener {override fun onItemClick(item: String) {// 处理点击事件}
})3. 伴生对象 伴生对象是在类内部定义的对象类似于 Java 的静态成员。它可以用于存放与类相关的静态方法或常量。
class MyFragment : Fragment() {companion object {const val ARG_KEY arg_keyfun newInstance(): MyFragment {return MyFragment()}}// 其他代码...
}在这个例子中companion object 中的内容可以像静态方法一样调用例如 MyFragment.newInstance()。 1.2 委托
委托Delegation是一种设计模式在Kotlin中可以通过委托属性和委托类来实现。它允许将对象的某些操作委托给另一个对象来处理从而实现代码的重用和解耦。
下面是关于委托的介绍
概念委托是一种通过将操作委托给另一个对象来实现代码复用和解耦的机制。委托对象Delegate负责处理实际的操作委托属性Delegated Property则将属性的访问和修改委托给委托对象。作用委托可以减少代码重复提高代码的可维护性和可读性。通过委托我们可以将特定的行为和功能从类中提取出来并交给专门的对象来处理。生活中的例子假设你是一个项目经理你委托你的团队成员完成一些具体的任务然后你收集并整合他们的工作成果。在这个例子中你是委托者团队成员是委托对象他们的工作成果是委托属性。使用步骤 创建委托对象定义一个实际处理操作的对象。创建委托属性在类中定义委托属性并将其初始化为委托对象。使用委托属性通过委托属性来访问和修改属性的值。 原理和底层实现委托属性通过将属性的访问和修改操作委托给委托对象来实现。在编译时Kotlin编译器会自动生成委托属性的委托方法并将其转化为对委托对象对应方法的调用。优点 代码复用委托可以将通用的操作和功能从类中提取出来实现代码的复用。解耦和模块化委托将关注点分离使得类的职责更加清晰提高了代码的可读性和可维护性。 缺点和注意事项 委托会引入额外的开销因为需要维护委托对象和委托属性之间的关系。注意避免委托循环即委托对象和委托属性相互依赖的情况。 应用场景 代码重用当多个类具有相似的操作和功能时可以使用委托将这些共同的部分提取出来实现代码的重用。解耦和扩展当需要在不修改原有类的情况下为类添加新的行为或功能时可以使用委托来实现解耦和模块化。
下面是一个具体案例的完整Kotlin代码演示了委托的使用
interface Worker {fun doWork()
}class TeamMember(private val name: String) : Worker {override fun doWork() {println($name is working on a task)}
}class ProjectManager(private val worker: Worker) : Worker by worker {fun collectResults() {println(Project Manager is collecting the results)}
}fun main() {val teamMember TeamMember(John)val projectManager ProjectManager(teamMember)projectManager.doWork()projectManager.collectResults()
}运行结果
John is working on a task
Project Manager is collecting the results在上述示例中我们定义了一个Worker接口其中包含一个doWork()方法。然后我们创建了一个TeamMember类实现了Worker接口并在doWork()方法中输出了团队成员的工作信息。
接下来我们创建了一个ProjectManager类它也实现了Worker接口并通过委托属性将工作委托给了传入的worker对象。ProjectManager类还定义了一个collectResults()方法用于收集工作结果。
在main函数中我们创建了一个TeamMember对象teamMember和一个ProjectManager对象projectManager并将teamMember传递给projectManager的构造函数进行委托。然后我们通过调用projectManager对象的方法来执行工作和收集结果。
通过使用委托ProjectManager类将实际的工作操作委托给了TeamMember对象实现了代码的重用和解耦。ProjectManager可以通过委托属性直接访问和调用TeamMember对象的方法从而实现了功能的扩展和模块化。 1.2.1 类的委托
在Kotlin中类的委托是一种通过将类的实现委托给其他类来实现代码重用和解耦的机制。通过类的委托可以将一个类的接口实现委托给另一个类从而避免代码的冗余并提高代码的可维护性。
下面是关于类的委托的介绍
概念类的委托是一种将类的接口实现委托给其他类来实现代码重用和解耦的机制。被委托的类负责实际的操作委托类通过将请求转发给被委托类来实现。作用类的委托可以减少代码重复提高代码的可读性和可维护性。通过委托我们可以将通用的操作和功能从类中提取出来并交给专门的类来处理。使用步骤 创建被委托的类定义一个实现接口的类负责实际的操作。创建委托类定义一个委托类并将接口的实现委托给被委托的类。使用委托类在需要使用被委托类功能的类中将委托类作为属性并调用委托类的方法。 原理和底层实现在类的委托中委托类将接口的实现委托给被委托的类通过将请求转发给被委托类来实现。在编译时Kotlin编译器会自动生成委托类的委托方法并将其转化为对被委托类对应方法的调用。优点 代码复用类的委托可以将通用的操作和功能从类中提取出来实现代码的复用。解耦和模块化类的委托将关注点分离使得类的职责更加清晰提高了代码的可读性和可维护性。 缺点和注意事项 委托会引入额外的开销因为需要维护委托类和被委托类之间的关系。注意避免委托循环即委托类和被委托类相互依赖的情况。 应用场景 接口实现当一个类需要实现多个接口时可以使用委托将其中一个或多个接口的实现委托给其他类。装饰器模式当需要在原有类的功能上添加额外的行为时可以使用委托来实现装饰器模式。
下面是一个具体案例的完整Kotlin代码演示了类的委托的使用
interface Printer {fun printMessage(message: String)
}class ConsolePrinter : Printer {override fun printMessage(message: String) {println(Printing message: $message)}
}class MessagePrinter(private val printer: Printer) : Printer by printer {fun printDecoratedMessage(message: String) {val decoratedMessage **********\n$message\n**********printMessage(decoratedMessage)}
}fun main() {val consolePrinter ConsolePrinter()val messagePrinter MessagePrinter(consolePrinter)messagePrinter.printDecoratedMessage(Hello, Kotlin!)
}运行结果
**********
Hello, Kotlin!
**********在上述示例中我们定义了一个Printer接口其中包含一个printMessage()方法。然后我们创建了一个ConsolePrinter类实现了Printer接口并在printMessage()方法中打印了消息。
接下来我们创建了一个MessagePrinter类它也实现了Printer接口并通过委托属性将打印消息的功能委托给了传入的printer对象。MessagePrinter类还定义了一个printDecoratedMessage()方法用于打印装饰后的消息。
在main函数中我们创建了一个ConsolePrinter对象consolePrinter和一个MessagePrinter对象messagePrinter并将consolePrinter传递给messagePrinter的构造函数进行委托。然后我们通过调用messagePrinter对象的方法来打印装饰后的消息。
通过使用类的委托MessagePrinter类将实际的打印操作委托给了ConsolePrinter对象实现了代码的重用和解耦。MessagePrinter可以通过委托属性直接访问和调用ConsolePrinter对象的方法从而实现了功能的扩展和模块化。 1.2.2 委托属性
在Kotlin中委托属性Delegated Property是一种特殊类型的属性它将属性的访问和修改委托给另一个对象来处理。委托属性提供了一种方便的方式来实现属性的延迟初始化、属性委托、属性拦截等功能以减少重复的代码并提高代码的可维护性。
下面是关于委托属性的介绍
概念委托属性是一种将属性的访问和修改委托给其他对象来处理的属性。委托属性本身只包含一个委托对象并通过委托对象来处理属性的操作。作用委托属性可以减少重复的代码实现属性的延迟初始化、属性委托、属性拦截等功能提高代码的可读性和可维护性。生活中的例子假设你是一个项目经理你委托你的团队成员完成一些具体的任务并在他们完成任务后收集任务结果。在这个例子中你是委托者团队成员是委托对象他们的任务结果是委托属性。使用步骤 创建委托对象定义一个对象负责实际处理属性的操作。创建委托属性在类中定义委托属性并将其初始化为委托对象。使用委托属性通过委托属性来访问和修改属性的值。 原理和底层实现委托属性通过将属性的访问和修改操作委托给委托对象来实现。在编译时Kotlin编译器会自动生成委托属性的委托方法并将其转化为对委托对象对应方法的调用。优点 代码复用委托属性可以将通用的属性操作从类中提取出来实现代码的复用。延迟初始化通过委托属性可以实现属性的延迟初始化只在需要时进行初始化。属性委托委托属性可以将属性的操作委托给其他对象来处理实现属性的委托。 注意事项 委托属性必须定义为var或val具体取决于属性是否可写。委托属性的委托对象必须提供属性的读取和写入方法。 应用场景 延迟初始化当属性的初始化成本较高或在首次访问时才需要初始化时可以使用委托属性实现延迟初始化。属性委托当需要将属性的操作委托给其他对象来处理时可以使用委托属性实现属性委托。
下面是一个延迟初始化委托属性的具体案例的完整Kotlin代码演示了委托属性的使用
class ExpensiveResource {init {println(Initializing expensive resource)}fun doSomething() {println(Doing something with expensive resource)}
}class ResourceHolder {val resource: ExpensiveResource by lazy {println(Lazy initializing resource)ExpensiveResource()}
}fun main() {val holder ResourceHolder()println(Accessing resource for the first time:)holder.resource.doSomething()println(Accessing resource for the second time:)holder.resource.doSomething()
}运行结果
Accessing resource for the first time:
Lazy initializing resource
Initializing expensive resource
Doing something with expensive resource
Accessing resource for the second time:
Doing something with expensive resource在上述示例中我们定义了一个ExpensiveResource类表示一个昂贵的资源它在初始化时输出一条消息。
然后我们创建了一个ResourceHolder类它包含一个委托属性resource类型为ExpensiveResource。属性的初始化通过lazy委托实现即只在首次访问时进行初始化。
在main函数中我们创建了一个ResourceHolder对象holder并通过访问holder.resource来使用资源。在第一次访问时委托属性进行了延迟初始化输出了相应的消息并执行了相应的操作。在第二次访问时委托属性已经初始化过了不再进行初始化直接执行操作。
通过使用委托属性的延迟初始化我们可以避免不必要的资源初始化提高性能和效率。只有在需要访问属性时才进行初始化实现了延迟加载的效果。 1.2.3 委托类的初始化函数
在Kotlin中委托类的初始化函数Delegate Initialization Function指的是在创建委托类实例时调用的函数用于初始化委托类的属性或执行其他必要的操作。委托类的初始化函数可以通过构造函数参数或自定义的初始化方法来实现。
下面是关于委托类的初始化函数的介绍
概念委托类的初始化函数是在创建委托类实例时调用的函数用于初始化委托类的属性或执行其他必要的操作。作用委托类的初始化函数用于在委托类实例创建时进行必要的初始化例如设置属性的初始值、执行一些准备工作等。使用步骤 定义委托类创建一个类作为委托类并定义初始化函数。实现初始化函数在委托类中实现初始化函数根据需要进行属性的初始化或其他操作。调用初始化函数在创建委托类实例时调用初始化函数来完成初始化。 原理和底层实现委托类的初始化函数实际上就是一个普通的函数可以通过构造函数参数传递所需的初始化值或者通过自定义的初始化方法来完成初始化操作。优点 灵活性通过委托类的初始化函数可以在创建委托类实例时执行一些定制化的初始化操作提供更灵活的初始化方式。可维护性将初始化逻辑封装在初始化函数中可以提高代码的可读性和可维护性。 注意事项 初始化函数应该在创建委托类实例时被调用以确保属性的正确初始化。初始化函数可以包含必要的参数以传递初始化所需的值。 应用场景 属性初始化当需要在创建委托类实例时对属性进行初始化时可以使用委托类的初始化函数。准备工作当需要在创建委托类实例时执行一些准备工作时可以使用委托类的初始化函数。
下面是一个具体案例的完整Kotlin代码演示了委托类的初始化函数的使用
class Connection {init {println(Establishing connection...)// 执行一些连接相关的初始化操作}fun executeQuery(query: String) {println(Executing query: $query)// 执行查询操作}
}class DatabaseClient(private val connection: Connection) {init {println(Initializing database client...)// 执行一些数据库客户端的初始化操作}fun performQuery(query: String) {connection.executeQuery(query)}
}fun main() {val connection Connection()val client DatabaseClient(connection)client.performQuery(SELECT * FROM users)
}运行结果
Establishing connection...
Initializing database client...
Executing query: SELECT * FROM users在上述示例中我们定义了一个Connection类表示数据库连接它在初始化时输出一条消息并执行一些连接相关的初始化操作。
然后我们创建了一个DatabaseClient类它包含一个委托属性connection类型为Connection。在DatabaseClient的初始化函数中我们输出了一条消息并执行了一些数据库客户端的初始化操作。
在main函数中我们首先创建了一个Connection对象connection它会执行连接相关的初始化操作。然后我们创建了一个DatabaseClient对象client将connection对象作为参数传递给DatabaseClient的构造函数进行委托。
最后我们通过调用client对象的performQuery方法来执行查询操作该方法内部会委托调用connection对象的executeQuery方法。
通过使用委托类的初始化函数我们可以在创建委托类实例时执行一些初始化操作确保属性的正确初始化和其他必要的准备工作。这样可以提高代码的可读性和可维护性同时提供了灵活的初始化方式。 1.2.4 委托的前提条件
在 Kotlin 中委托是一种强大的设计模式允许一个类将某些特定的功能实现委托给另一个类从而减少代码重复和增加代码复用性。使用委托可以通过组合来实现类似于多继承的效果。
然而委托需要满足一些前提条件才能使用
接口委托被委托的类必须实现一个接口委托类则要通过实现同样的接口来提供委托功能。属性委托被委托的类必须是属性property而不是普通字段fieldKotlin 中的属性由 val 或 var 关键字声明。使用关键字 by在使用委托时需要使用关键字 by 将委托类与被委托的类关联起来。接口中的方法或属性需要被覆盖被委托的类必须覆盖接口中的所有方法或属性委托类则实现这些方法或属性的具体实现。委托类要实例化委托类必须在被委托的类中实例化。
下面是一个使用接口委托的简单示例
// 定义接口
interface Printer {fun printMessage(message: String)
}// 实现委托的类
class ConsolePrinter : Printer {override fun printMessage(message: String) {println(Printing: $message)}
}// 被委托的类
class MessageProcessor(printer: Printer) : Printer by printer {// 这里不需要实现 printMessage() 方法委托类 ConsolePrinter 将提供实现
}fun main() {val consolePrinter ConsolePrinter()val messageProcessor MessageProcessor(consolePrinter)messageProcessor.printMessage(Hello, Kotlin!) // 使用委托进行打印
}在上述示例中我们定义了一个接口 Printer一个实现了 Printer 接口的 ConsolePrinter 类和一个被委托的 MessageProcessor 类。MessageProcessor 类通过 by 关键字将打印功能委托给 Printer 接口的实现这里是 ConsolePrinter。
总结Kotlin 中使用委托的前提条件是被委托的类必须实现一个接口并通过 by 关键字将委托类与被委托的类关联起来委托类则实现接口中的方法或属性的具体实现。 1.2.5 kotlin委托在Android中的使用
在 Android 中Kotlin 委托是一种非常有用的设计模式可以帮助简化代码并增加代码复用性。Kotlin 委托在 Android 中的使用主要涉及两个方面属性委托和接口委托。
属性委托 在 Android 中属性委托常用于简化视图绑定比如使用 findViewById 获取视图并将其与活动Activity或片段Fragment中的属性绑定。通过使用属性委托可以避免在每次使用视图时都手动调用 findViewById从而简化代码并提高可读性。
Android 中通常使用 kotlin-android-extensions 或 View Binding 来实现属性委托。这两种方式都能够自动处理视图绑定让你能够像访问普通属性一样访问视图。例如
使用 kotlin-android-extensions
import kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 不再需要手动调用 findViewByIdtextView.text Hello, Kotlin with Android Extensions!}
}使用 View Binding
private lateinit var binding: ActivityMainBindingclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding ActivityMainBinding.inflate(layoutInflater)val view binding.rootsetContentView(view)// 通过 View Binding 访问视图binding.textView.text Hello, Kotlin with View Binding!}
}接口委托 在 Android 中接口委托常用于实现一些通用的行为或功能并在多个类之间共享这些实现。一个常见的例子是 RecyclerView 的适配器Adapter。
在 RecyclerView 的适配器中可以使用接口委托来实现视图的创建和数据绑定逻辑以及处理点击事件等。通过委托可以将这些逻辑从活动Activity或片段Fragment中分离出来使得代码更加模块化和易于维护。
以下是 RecyclerView 适配器的简化示例
class MyAdapter(private val itemList: ListString) : RecyclerView.AdapterMyAdapter.ViewHolder() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {val itemView LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)return ViewHolder(itemView)}override fun onBindViewHolder(holder: ViewHolder, position: Int) {val item itemList[position]holder.bind(item)}override fun getItemCount() itemList.sizeclass ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {fun bind(item: String) {itemView.textView.text item// 处理点击事件等其他逻辑itemView.setOnClickListener {// 处理点击事件}}}
}在上面的示例中我们使用了接口委托来实现 RecyclerView 适配器将视图的创建和数据绑定逻辑委托给 onCreateViewHolder 和 onBindViewHolder 方法。这样可以使得适配器代码更加简洁和可维护。
总结在 Android 中Kotlin 委托主要用于简化属性绑定和实现通用功能。属性委托可以通过 kotlin-android-extensions 或 View Binding 来实现自动视图绑定而接口委托可以用于实现通用逻辑例如 RecyclerView 的适配器。使用委托能够提高代码的可读性和可维护性同时减少重复性代码。 1.3 标准委托
在Kotlin中标准委托Standard Delegates是一组内置的委托属性用于简化常见的委托模式的实现。它们提供了一种简单而方便的方式来实现属性的委托并解决了一些常见的问题。
下面是关于标准委托的介绍
概念标准委托是一组内置的委托属性用于简化常见的委托模式的实现。作用标准委托提供了一种简单而方便的方式来实现属性的委托可以减少重复的代码并解决一些常见的问题如懒加载、观察属性变化等。生活中的例子想象一个场景你需要在一个对象中缓存某个值当需要访问该值时如果已经缓存过则直接返回缓存的值如果没有缓存则计算出值并进行缓存。这种情况下你可以使用标准委托中的lazy委托来实现延迟初始化和缓存功能。使用步骤 导入标准委托在代码中导入标准委托的相关类或函数它们位于kotlin.properties包中。应用标准委托在需要委托属性的地方使用标准委托来声明属性指定委托对象和相关参数。 原理和底层实现标准委托是通过封装常见的委托模式和功能使用特定的委托类或函数来实现的。底层实现利用了属性委托的语法和机制。优点 简化代码标准委托提供了一种简单的方式来实现属性的委托减少了重复的代码和样板代码的编写。提供常见功能标准委托解决了一些常见的问题如延迟初始化、懒加载、属性变化观察等。 注意事项 熟悉标准委托的特性和使用方式以确保正确地选择和应用适合的标准委托。注意标准委托的适用范围和限制避免滥用和误用。 应用场景 延迟初始化当需要在首次访问时进行延迟初始化时可以使用lazy委托。懒加载当需要在首次访问时进行懒加载时可以使用lazy委托。属性变化观察当需要观察属性变化并执行相应操作时可以使用observable委托。
下面是一个具体案例的完整Kotlin代码演示了标准委托的使用
import kotlin.properties.Delegatesclass User {var name: String by Delegates.observable(no name) { property, oldValue, newValue -println(Property ${property.name} changed from $oldValue to $newValue)}
}fun main() {val user User()user.name Alice // 属性变化触发观察者函数user.name Bob // 属性变化触发观察者函数
}运行结果
Property name changed from no name to Alice
Property name changed from Alice to Bob在上述示例中我们定义了一个User类其中的name属性使用了Delegates.observable标准委托。该委托允许我们在属性的值发生变化时触发观察者函数。
在main函数中我们创建了一个User对象user。然后我们将user的name属性分别设置为Alice和Bob每次属性变化都会触发观察者函数并输出属性变化的信息。
通过使用Delegates.observable标准委托我们实现了属性变化的观察功能而无需显式编写观察者模式的相关代码。这样可以减少了重复的代码并提供了一种简单而方便的方式来实现属性的委托和观察。 1.3.1 惰性装载
在 Kotlin 中惰性装载Lazy Loading是一种常见的使用标准委托的技术它允许在首次访问时延迟初始化对象从而提高性能和节省资源。惰性装载通常用于需要耗时初始化或昂贵资源的情况。
下面是关于惰性装载的介绍
概念惰性装载是一种延迟初始化对象的技术即在首次访问时才进行对象的创建和初始化。作用惰性装载可以提高性能和节省资源特别是在对象初始化耗时较长或需要昂贵资源的情况下。生活中的例子想象一个场景你有一个数据库连接对象创建和初始化该对象可能需要花费一定的时间和资源。如果你的应用程序在启动时不需要立即使用该数据库连接那么可以使用惰性装载来延迟初始化该对象直到第一次需要使用它的时候才进行创建和初始化。使用步骤 导入标准委托在代码中导入标准委托的相关类或函数lazy 是惰性装载的标准委托。应用惰性装载在需要进行惰性装载的属性上使用 lazy 委托来声明并提供一个 lambda 表达式作为惰性初始化逻辑。 原理和底层实现惰性装载使用了标准委托中的 lazy 委托该委托通过线程安全的方式来保证对象只会被初始化一次。优点 延迟初始化惰性装载允许在首次访问时才进行对象的创建和初始化避免了不必要的初始化操作。提高性能和节省资源在耗时初始化或昂贵资源的情况下惰性装载可以提高性能和节省系统资源。 注意事项 惰性装载适用于那些在首次访问之前不需要立即初始化的对象。需要注意惰性装载的线程安全性确保在多线程环境下也能正确进行初始化。 应用场景 耗时初始化的对象当对象的初始化过程耗时较长时可以使用惰性装载来推迟初始化直到需要使用该对象时才进行初始化。昂贵资源的对象当对象需要昂贵的资源如数据库连接、文件加载等时可以使用惰性装载来避免不必要的资源消耗。
下面是一个具体案例的完整 Kotlin 代码演示了惰性装载的使用
val lazyValue: String by lazy {println(Initializing lazyValue)Hello, Lazy!
}fun main() {println(Before accessing lazyValue)println(lazyValue) // 首次访问时进行初始化println(After accessing lazyValue)
}运行结果
Before accessing lazyValue
Initializing lazyValue
Hello, Lazy!
After accessing lazyValue在上述示例中我们使用 lazy 委托来实现惰性装载。声明了一个名为 lazyValue 的属性该属性使用 lazy 委托进行惰性初始化。我们提供了一个 lambda 表达式作为惰性初始化逻辑在首次访问 lazyValue 时会执行该 lambda 表达式进行初始化。
在 main 函数中我们首先输出 “Before accessing lazyValue”然后访问 lazyValue 属性它会触发初始化输出 “Initializing lazyValue”。接着打印出 lazyValue 的值 “Hello, Lazy!”最后输出 “After accessing lazyValue”。
通过使用 lazy 委托我们实现了惰性装载的功能lazyValue 属性在首次访问时进行初始化避免了不必要的初始化操作从而提高了性能和节省了资源。 1.3.2 可观察属性
在 Kotlin 中可观察属性Observable Properties是一种标准委托它允许我们在属性值发生变化时监听并做出相应的反应。通过可观察属性我们可以轻松地实现属性值的观察和响应。
下面是关于可观察属性的介绍
概念可观察属性是一种标准委托用于监听属性值的变化并做出相应的反应。作用可观察属性提供了一种简单的方式来观察和响应属性值的变化可以在属性发生变化时执行自定义的操作。生活中的例子想象一个场景你有一个温度传感器它会定期检测当前的温度值。你希望能够实时监控温度的变化并在温度超过某个阈值时触发报警。这种情况下你可以使用可观察属性来监听温度值的变化并在超过阈值时执行报警操作。使用步骤 导入标准委托在代码中导入标准委托的相关类或函数Delegates.observable 是可观察属性的标准委托。应用可观察属性在需要观察的属性上使用 Delegates.observable 委托来声明并提供一个 lambda 表达式作为属性变化的回调函数。 原理和底层实现可观察属性使用了标准委托中的 Delegates.observable 委托该委托通过在属性赋值时进行拦截和回调函数的调用来监听属性值的变化。优点 简化代码可观察属性提供了一种简单的方式来监听属性值的变化避免了手动编写监听器的复杂逻辑。定制化操作可以根据需求在属性值变化时执行自定义的操作实现灵活的响应机制。 注意事项 可观察属性适用于那些需要在属性值变化时执行操作的场景。需要注意回调函数的执行时机和顺序确保在合适的时机执行相应的操作。 应用场景 属性变化的监听和响应当需要在属性值变化时执行自定义操作时可以使用可观察属性来实现属性的监听和响应。
下面是一个具体案例的完整 Kotlin 代码演示了可观察属性的使用
import kotlin.properties.Delegatesclass TemperatureSensor {var temperature:Int by Delegates.observable(0) { property, oldValue, newValue -println(Temperature changed from $oldValue°C to $newValue°C)if (newValue 30) {println(Temperature too high! Triggering alarm...)// 触发报警逻辑}}
}fun main() {val sensor TemperatureSensor()sensor.temperature 25 // 温度变化触发监听器输出温度变化信息sensor.temperature 35 // 温度变化触发监听器输出温度变化信息并触发报警
}运行结果
Temperature changed from 0°C to 25°C
Temperature changed from 25°C to 35°C
Temperature too high! Triggering alarm...在上述示例中我们定义了一个 TemperatureSensor 类其中的 temperature 属性使用了 Delegates.observable 标准委托。该委托允许我们在属性值发生变化时触发回调函数并在回调函数中进行相应的操作。
在 main 函数中我们创建了一个 TemperatureSensor 对象 sensor。然后我们将 sensor 的 temperature 属性分别设置为 25 和 35每次属性变化都会触发回调函数并输出温度变化的信息。当温度超过 30 时还会触发报警操作。
通过使用 Delegates.observable 标准委托我们实现了可观察属性的功能可以轻松地监听属性值的变化并在需要时执行自定义的操作。这样可以提供灵活的属性监控和响应机制简化了代码的编写和维护。 1.3.3 阻止属性的赋值操作
在 Kotlin 中阻止属性的赋值操作是一种常见的需求可以通过使用标准委托中的 ReadOnlyProperty 来实现。这种委托可以确保属性只能在初始化时被赋值一次并阻止后续的赋值操作。
下面是关于阻止属性赋值的介绍
概念阻止属性赋值是一种使用标准委托的技术用于确保属性只能在初始化时被赋值一次并阻止后续的赋值操作。作用阻止属性赋值可以保护属性的不可变性防止在初始化后被意外地修改。生活中的例子想象一个场景你有一个订单类其中的订单号是在创建订单时自动生成的并且不能在后续修改。这种情况下你可以使用阻止属性赋值的技术确保订单号只能在初始化时被赋值一次并阻止后续的修改操作。使用步骤 导入标准委托在代码中导入标准委托的相关类或函数ReadOnlyProperty 是用于阻止属性赋值的标准委托。应用阻止属性赋值在需要阻止赋值的属性上使用 ReadOnlyProperty 委托来声明并提供一个初始化值。 原理和底层实现阻止属性赋值的委托会在初始化时将属性值保存起来并在后续的赋值操作中抛出异常阻止属性的修改。优点 保护属性的不可变性阻止属性赋值可以确保属性只能在初始化时被赋值一次并阻止后续的修改操作。 注意事项 阻止属性赋值适用于需要保护属性不被修改的场景。需要注意在初始化时正确赋值属性并避免后续的赋值操作。 应用场景 不可变属性当需要确保属性在初始化后不被修改时可以使用阻止属性赋值的技术。
下面是一个具体案例的完整 Kotlin 代码演示了阻止属性赋值的使用
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KPropertyclass Order {val orderNumber: Int by ReadOnlyProperty { _, property -if (property.name ! orderNumber) {throw UnsupportedOperationException(Cannot modify property ${property.name})}12345 // 初始化值}
}fun main() {val order Order()println(order.orderNumber) // 输出12345// 尝试修改属性值将会抛出异常order.orderNumber 67890 // 抛出 UnsupportedOperationException
}运行结果
12345
Exception in thread main java.lang.UnsupportedOperationException: Cannot modify property orderNumber在上述示例中我们定义了一个 Order 类其中的 orderNumber 属性使用了 ReadOnlyProperty 标准委托。该委托确保属性只能在初始化时被赋值一次并阻止后续的赋值操作。
在 main 函数中我们创建了一个 Order 对象 order。然后我们打印出 order 的 orderNumber 属性的值输出为 12345。接着我们尝试修改 orderNumber 的值为 67890但这会导致抛出 UnsupportedOperationException 异常表示属性不可修改。
通过使用 ReadOnlyProperty 标准委托我们实现了阻止属性赋值的功能确保属性只能在初始化时被赋值一次并阻止后续的修改操作。这样可以保护属性的不可变性提高代码的可靠性和安全性。 1.3.4 Map委托
Map 委托是 Kotlin 中的标准委托之一它允许我们将属性的存储和访问委托给一个 Map 对象。通过使用 Map 委托我们可以方便地将属性与 Map 中的键值对关联起来实现属性的动态存储和访问。
下面是关于 Map 委托的介绍
概念Map 委托是一种标准委托它允许我们将属性的存储和访问委托给一个 Map 对象。作用Map 委托提供了一种便捷的方式来将属性与 Map 中的键值对关联起来实现属性的动态存储和访问。生活中的例子想象一个场景你有一个配置文件其中包含了一些属性和对应的值。你希望能够以属性的形式访问这些配置值同时能够动态添加或修改配置项。这种情况下你可以使用 Map 委托将属性与配置文件中的键值对关联起来。使用步骤 创建一个 Map 对象创建一个可包含属性键值对的 Map 对象可以是可变的 MutableMap 或不可变的 Map。应用 Map 委托在需要关联的属性上使用 Map 委托来声明提供对应的 Map 对象和属性键。 原理和底层实现Map 委托通过在属性的存储和访问过程中将相关操作委托给关联的 Map 对象来实现。优点 动态属性存储通过 Map 委托可以将属性的存储和访问与动态的 Map 对象关联起来实现灵活的属性存储和访问。简化配置管理使用 Map 委托可以方便地管理配置文件以属性的形式访问配置项。 注意事项 确保 Map 中包含了与属性关联的键值对否则会导致访问属性时出现异常。可根据需要选择使用可变的 MutableMap 或不可变的 Map根据是否允许修改属性值来选择合适的 Map 类型。 应用场景 属性动态存储当属性的存储和访问需要与动态的 Map 对象关联时可以使用 Map 委托实现属性的动态存储和访问。
下面是一个具体案例的完整 Kotlin 代码演示了 Map 委托的使用
import kotlin.reflect.KPropertyclass ConfigDelegate(private val config: MapString, String) {operator fun getValue(thisRef: Any?,property: KProperty*): String {return config[property.name] ?: throw IllegalArgumentException(Property ${property.name} not found in config)}
}class AppConfig {private val configMap mapOf(apiUrl to https://api.example.com,apiKey to your-api-key)val apiUrl: String by ConfigDelegate(configMap)val apiKey: String by ConfigDelegate(configMap)
}fun main() {val appConfig AppConfig()println(appConfig.apiUrl) // 输出https://api.example.comprintln(appConfig.apiKey) // 输出your-api-key
}运行结果
https://api.example.com
your-api-key在上述示例中我们定义了一个 ConfigDelegate 类它实现了 getValue 操作符函数用于从关联的 Map 中获取属性的值。
然后我们创建了一个 AppConfig 类其中的 apiUrl 和 apiKey 属性使用了 ConfigDelegate Map 委托关联了一个名为 configMap 的 Map 对象。
在 main 函数中我们创建了一个 AppConfig 对象 appConfig然后通过访问 appConfig.apiUrl 和 appConfig.apiKey 属性分别获取了配置中的 URL 和 API Key并将其打印出来。
通过使用 Map 委托我们实现了属性的动态存储和访问将属性与 Map 中的键值对关联起来。这样可以方便地管理配置文件、实现动态属性存储等场景。 1.3.5 MutableMap委托
MutableMap 委托是 Kotlin 中的标准委托之一它允许我们将属性的存储和访问委托给一个可变的 Map 对象。通过使用 MutableMap 委托我们可以方便地将属性与 MutableMap 中的键值对关联起来实现属性的动态存储和访问并且允许修改属性的值。
下面是关于 MutableMap 委托的介绍
概念MutableMap 委托是一种标准委托它允许我们将属性的存储和访问委托给一个可变的 Map 对象。作用MutableMap 委托提供了一种便捷的方式来将属性与 MutableMap 中的键值对关联起来实现属性的动态存储和访问并且允许修改属性的值。生活中的例子想象一个场景你有一个用户类其中的属性包括用户ID、用户名等。你希望能够以属性的形式访问和修改这些用户属性并且能够动态地添加或删除属性。这种情况下你可以使用 MutableMap 委托将属性与一个可变的 Map 对象关联起来实现属性的动态存储和访问。使用步骤 创建一个 MutableMap 对象创建一个可变的 MutableMap 对象用于存储属性的键值对。应用 MutableMap 委托在需要关联的属性上使用 MutableMap 委托来声明提供对应的 MutableMap 对象和属性键。 原理和底层实现MutableMap 委托通过在属性的存储和访问过程中将相关操作委托给关联的MutableMap 对象来实现。优点 动态属性存储通过 MutableMap 委托可以将属性的存储和访问与动态的 MutableMap 对象关联起来实现灵活的属性存储和访问并允许修改属性的值。 注意事项 确保 MutableMap 中包含了与属性关联的键值对否则可能会导致访问属性时出现异常。需要注意在修改属性值时同时更新 MutableMap 中对应的键值对。 应用场景 动态属性存储和访问当属性的存储和访问需要与动态的 MutableMap 对象关联并且允许修改属性的值时可以使用 MutableMap 委托实现动态属性的存储和访问。
下面是一个具体案例的完整 Kotlin 代码演示了 MutableMap 委托的使用
import kotlin.reflect.KPropertyclass User{private val properties mutableMapOfString, Any?()operator fun T getValue(thisRef: Any?, property: KProperty*): T {return properties[property.name] as? T ?: throw IllegalArgumentException(Property ${property.name} not found)}operator fun T setValue(thisRef: Any?, property: KProperty*, value: T) {properties[property.name] value}
}fun main() {val user User()user.name Aliceuser.age 25println(user.name) // 输出Aliceprintln(user.age) // 输出25
}运行结果
Alice
25在上述示例中我们定义了一个 User 类其中的属性存储在一个可变的 MutableMap 对象 properties 中。
通过实现 getValue 和 setValue 操作符函数我们将属性的存储和访问委托给 properties MutableMap 对象。
在 main 函数中我们创建了一个 User 对象 user。然后我们使用属性赋值的方式给 name 和 age 属性赋值。接着我们通过属性访问的方式获取 name 和 age 的值并将其打印出来。
通过使用 MutableMap 委托我们实现了属性的动态存储和访问并且允许修改属性的值。这样可以方便地管理动态属性、实现属性的灵活存储和访问。 1.3.6 kotlin标准委托在Android中的使用
在 Kotlin 中标准委托是一组委托属性包括 lazy、observable、vetoable 等。这些标准委托属性在 Android 中也同样适用它们可以帮助简化代码并增加代码的可读性和可维护性。
以下是在 Android 中使用 Kotlin 标准委托的示例
1. lazy 委托 lazy 委托用于实现延迟初始化直到第一次访问属性时才会进行初始化。这在 Android 中经常用于初始化视图或执行一些耗时的操作避免不必要的初始化和资源浪费。
class MainActivity : AppCompatActivity() {// 使用 lazy 委托来延迟初始化视图private val textView: TextView by lazy {findViewById(R.id.textView)}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 第一次访问 textView 时进行初始化textView.text Hello, Kotlin with lazy delegate!}
}2. observable 委托 observable 委托用于监听属性的变化并在属性值发生变化时执行相应的操作。这在 Android 中可以用于实现视图与数据的绑定当数据变化时自动更新视图。
class UserViewModel : ViewModel() {// 使用 observable 委托来监听 userName 属性的变化var userName: String by Delegates.observable() { _, oldValue, newValue -// 属性值发生变化时执行相应的操作例如更新视图updateView(newValue)}private fun updateView(newUserName: String) {// 更新视图的逻辑}
}3. vetoable 委托 vetoable 委托用于在属性赋值之前进行额外的校验或操作并可以决定是否接受新的属性值。
class SettingsFragment : Fragment() {// 使用 vetoable 委托来限制最大文本长度为 10var editTextContent: String by Delegates.vetoable() { _, _, newValue -newValue.length 10}// 其他代码...
}在上述示例中如果尝试将 editTextContent 属性赋值为超过 10 个字符的文本委托将拒绝接受这个新值并保持属性原有的值。