当前位置:网站首页>Android kotlin class delegation by, by lazy key
Android kotlin class delegation by, by lazy key
2022-06-21 17:30:00 【Lighthouse @kuaidao】
Preface
Contact kotlin Language has been around for a few years . It is also recommended to use in daily development work kotlin, But for some kotlin The details of language grammar have not been systematically studied . The knowledge points of fragments make the work meet with obstacles repeatedly , I started to study a few days ago compose When , Realize that the foundation is not well laid , Recently, I have been reviewing in stages kotlin Language grammar knowledge points . And unified output .
Turn off
Class delegation : Use “by” The key
keyword by Here's the problem :
There are vulnerabilities caused by inherited implementations , Base classes are inherited by subclasses and extend some functions , In this way, the subclass depends on the implementation details of the parent class . With constant iteration , The implementation details in the parent class will be modified with the iteration . Early assumptions about the implementation details of the parent class will also fail , Eventually, the program ends up with incorrect behavior . therefore kotin The original intention of the design is to identify such problems . Define the class default access modifier as final , Cannot inherit . If you want to extend a class that cannot be inherited , Decorative design patterns provide ready-made solutions .
by keyword , The underlying principle is that the system will help us automatically generate some Decoration design mode Template code to be implemented . Make the class structure clearer
Above is the manual implementation of the proxy , The following example uses by keyword , The system generates the template code of the installation mode
/** * creat time 2022/6/13 Afternoon 9:00 * author kuaidao * email : [email protected] * Decorator mode : Implement the same interface as the decorated class , Hold decorated objects . */
class DelegatingCollection<T>:Collection<T>{
val _list=ArrayList<T>()
override val size: Int
get() = _list.size
override fun contains(element: T): Boolean {
return _list.contains(element)
}
override fun containsAll(elements: Collection<T>): Boolean {
return _list.containsAll(elements)
}
override fun isEmpty(): Boolean {
return _list.isEmpty()
}
override fun iterator(): Iterator<T> {
return _list.iterator()
}
}
// You can target the proxy interface , Use by keyword
class DelegateCollect( innerList:ArrayList<T> = arrayListOf<T>()):Collection<T> by innerList{
}
Decorator design pattern :
Essentially create a new class , Implement the same interface as the original class , And cache the original class with a field , Code with the same behavior is implemented by the original class , Some other decorating code can be added before and after the original class behavior code is transferred . This keeps the original class api Without change , A functional extension of the original class , The role of decoration
Delegate properties : Reusable attribute access logic
Delegate properties : Is to delegate the accessor logic of a property to a Helpers Called entrustment ), The default attribute change listening interface is provided , You can define a listening callback to receive a notification event when the property changes .
Basic grammar
class Foo{
val type:Type by Deletegate()
}
// Specify that the delegate object must contain setValue,getValue Method ( Corresponding var Type attribute )
class Deletegate{
operator fun getValue()
operator fun setValue(type:Type)
}
fun main(){
val foo =Foo()
foo.type // Equivalent to deletegate.getValue()
foo.type = type Type values // Equivalent to deltegate.setValue()
}
Lazy initialization and by lazy{ }
Lazy initialization is no stranger to front-line development ,fragment Lazy loading . It is time-consuming to obtain resources , The general processing method is delayed initialization . It will not be initialized until it is used for the first time , When it is used again, it will directly return the initialized object reference or resource . No more initialization
import java.util.*
/** * creat time 2022/6/14 In the morning 10:29 * author kuaidao * email : [email protected] * Lazy initialization */
class SupportProperty{
private val _resources:List<Resources>?=null
private val _resources2:List<Resources>?=null
private val _resources3:List<Resources>?=null
val resources:List<Resources>
get() {
if(_resources==null){
_resources=initResources()
}else{
_resources
}
}
}
class Resources{
}
fun main(args: Array<String>) {
val supportProperty=SupportProperty()
// The first access initializes the resource
supportProperty.resources
// The second access will use the first loaded resource
supportProperty.resources
}
It's used here Support attribute technology , One _resource Used to store resource cache , The other is used to get resources , Previous _resources It can be for null, The latter will not be null, Through the code presentation, you can see that it is only for resource An inert initialization process is performed , Then, if a class needs to perform lazy initialization for multiple resource accesses , Heap code is not a good solution .kotlin by lazy{} Help us provide an inert initialization scheme .
Same code , One line has finished the lazy initialization .
class SupportProperty{
private val _resources:List<Resources> by lazy {
initResources()}
}
lazy The parameter of is a lambda expression , The object returned by the expression needs to implement getValue,setValue Can be used in this way . By default lazy It's thread safe . Here, the system provides three interfaces for thread safe mode settings
public enum class LazyThreadSafetyMode {
/** * Locks are used to ensure that only a single thread can initialize the [Lazy] instance. */
SYNCHRONIZED,
/** * Initializer function can be called several times on concurrent access to uninitialized [Lazy] instance value, * but only the first returned value will be used as the value of [Lazy] instance. */
PUBLICATION,
/** * No locks are used to synchronize an access to the [Lazy] instance value; if the instance is accessed from multiple threads, its behavior is undefined. * * This mode should not be used unless the [Lazy] instance is guaranteed never to be initialized from more than one thread. */
NONE,
}
for example :
private val _resources:List<Resources> by lazy(LazyThreadSafetyMode.NONE) {
initResources()}
Manually implement delegate properties
The following code , By providing PropertyChangeSupport Attribute change notification listening interface , When the attribute is modified , send out firePropertyChange( ) Change event , Set up a PropertyChangeListener() monitor , You can receive the notification after the property is modified .
/** * creat time 2022/6/13 Afternoon 10:10 * author kuaidao * email : [email protected] * Property change monitoring , You need to add changes to every possible attribute and send change events , also bean You need to inherit the attribute change listening interface */
open class propertyChangeAware{
val changeSupport=PropertyChangeSupport(this)
fun addChangeSupportListener(listener: PropertyChangeListener){
changeSupport.addPropertyChangeListener(listener)
}
fun removeSupportChangeListener(listener: PropertyChangeListener){
changeSupport.removePropertyChangeListener(listener)
}
}
class Persion(val name:String,age:Int):propertyChangeAware(){
var age:Int=age
set(value){
val oldValue=field
field=value
changeSupport.firePropertyChange("age",oldValue, field)
}
}
fun main(args: Array<String>) {
val p=Persion("kuangdao",18)
println(p.toString() +" True value ")
p.addChangeSupportListener(object : PropertyChangeListener {
override fun propertyChange(evt: PropertyChangeEvent) {
println("propter =${
evt.propertyName} oldvalue=${
evt .oldValue} newValue=${
evt.newValue}")
}
})
println(" Adjust to 100")
p.age=100
}
It's just for age Property makes a change listener , If you need to listen for multiple attribute changes , The code can be extracted and reused .
class ObservableProperty<T>(val name:String,val value:T,val changeSupport:PropertyChangeSupport){
fun getvalue():T=value
fun setValue(newValue){
val oldValue=value
value=newValue
changeSupport.firePropertyChange("age",oldValue, newValue)
}
}
}
As above Kotin The delegate properties Feature of the allows you to delegate to these boilerplate code .kotlin Implementation code path
common/kotlin/properties/ObservableProperty.kt In bag
public abstract class ObservableProperty<V>(initialValue: V) : ReadWriteProperty<Any?, V> {
private var value = initialValue
/** * The callback which is called before a change to the property value is attempted. * The value of the property hasn't been changed yet, when this callback is invoked. * If the callback returns `true` the value of the property is being set to the new value, * and if the callback returns `false` the new value is discarded and the property remains its old value. */
protected open fun beforeChange(property: KProperty<*>, oldValue: V, newValue: V): Boolean = true
/** * The callback which is called after the change of the property is made. The value of the property * has already been changed when this callback is invoked. */
protected open fun afterChange(property: KProperty<*>, oldValue: V, newValue: V): Unit {
}
public override fun getValue(thisRef: Any?, property: KProperty<*>): V {
return value
}
public override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {
val oldValue = this.value
if (!beforeChange(property, oldValue, value)) {
return
}
this.value = value
afterChange(property, oldValue, value)
}
}
Transformation rules of delegate attributes
class Foo{
val type:Type by Deletegate()
}
Deletegate The instance will be saved in a hidden property , be called , The compiler will also use a Kproperty Type object to represent this property is called , Compiler generated code
public final class Foo {
// $FF: synthetic field
static final KProperty[] $$delegatedProperties = new KProperty[]{
(KProperty)Reflection.property1(new PropertyReference1Impl(Foo.class, "type", "getType()I", 0))};
@NotNull
private final Deletegate type$delegate = new Deletegate();
public final int getType() {
return this.type$delegate.getValue(this, $$delegatedProperties[0]);
}
}
Compiled code callbacks direct access to properties to proxy objects type$delegate.getValue( this, attribute )
This mechanism makes it easy for us to do some operations on property access , For example, the location of custom attribute storage (map, database ), Do some verification when accessing this attribute .
stay map Save attribute values in
/** * creat time 2022/6/14 In the morning 11:23 * author kuaidao * email : [email protected] */
class Person{
private val _resource = hashMapOf<String,String>()
fun setAttribe(name:String,value:String){
_resource.put(name,value)
}
val name:String
get() {
return _resource["name"]!!
}
val company:String by _resource
}
fun main(args: Array<String>) {
val p=Person();
val data = mapOf( "name" to "kuaiao","company" to "codeReview")
for((key,value) in data){
p.setAttribe(key,value)
}
//println(p.name)
println(p.company)
}
Property corresponds to map Medium key.
summary :
Delegate properties can be used to reuse logic , These logic control how to store 、 initialization 、 Accessing and modifying attribute values ,lazy Standard library functions provide a simple way to implement lazy initialization properties ,Delegates.observable Function can be used to add observers for property changes , Delegate properties can use any map As a property delegate , To flexibly handle objects with variable attribute sets
边栏推荐
- 第八章 可编程接口芯片及应用【微机原理】
- Redis6.0新特性(上)
- Template: p6114 [template] Lyndon Decomposition & runs (string)
- How to connect the Internet - FTTH
- 【349期】面试官:如何优雅的自定义 ThreadPoolExecutor 线程池?
- 程序员进修之路
- 快速排序简单思路及程序
- Application of integrated servo motor and Schneider PLC tm241cec24t under CANopen Protocol
- 碳排放的计算
- List set map in kotlin
猜你喜欢

新增Razor组件支持代理连接RDP,JumpServer堡垒机v2.23.0发布

关于SSM整合,看这一篇就够了~(保姆级手把手教程)

很多软件公司,其实都是“笑话”

还在用 Xshell ?试试这款炫酷的 SSH 终端工具吧,功能很强大!

垃圾回收器

大话内存四区

Comparison of UDP and TCP

Still using xshell? Try this cool SSH terminal tool, which is very powerful!

data type

Notice on the third national operation research / data, model and decision-making course teaching seminar in 2022
随机推荐
Vector data download for mainland and global epidemic data, based on geo JSON to SHP
Kotlin DSL build
MATLAB实现的基于对称TSP问题研究
牛客网:验证IP地址
Kotlin DSL构建
path.join() 、path.basename() 和 path.extname()
一体化伺服电机与施耐德PLC TM241CEC24T在Canopen协议下的应用
全国行政区划
使用PicGo-Core 和 阿里云 实现typora图片自动上传
【mysql学习笔记19】多表查询
变量与指针
建立自己的网站(11)
QT5知识:字符串列表QStringListModel
【mysql学习笔记14】DQL语句执行顺序
[ros2 basics] Introduction to navigation2 navigation system
容器云是什么意思?与堡垒机有什么区别?
[MySQL learning notes 16] permission management
【mysql学习笔记11】排序查询
variable
我的小工具-卡片学习APP 完成啦