Kotlin类委托(二):实现原理及注意事项

相关文章

Kotlin 类委托(一):如何把一个列表页优化到十几行代码

Kotlin 类委托(二):实现原理及注意事项

上章留下的问题

​ 有看过我上一篇文章的读者可能会有疑问,为什么对网络数据的请求要使用 lambda 对象 getArticleList 的方式调用,在不同的 viewModelinit 方法块中进行设置,为什么不使用在 接口 中声明,在子类中 重写 的方式实现呢?我们改用这样的方式实现看一下效果:

  1. ArticleListPagingInterface 中添加方法用于获取数据

    /** 分页获取数据相关接口 */
    interface ArticleListPagingInterface {
    
        ... 省略部分代码 ...
        
        /** 获取文章列表数据 */
        fun getArticleList(num: Int): LiveData<NetResult<ArticleListEntity>>
        
        ... 省略部分代码 ...
    }
    
  2. ArticleListPagingInterfaceImpl 中添加对应实现

    /** 分页获取数据相关接口实现类 */
    class ArticleListPagingInterfaceImpl
        : ArticleListPagingInterface {
             
        ... 省略部分代码 ...
        
        /** 获取文章列表数据 */
        override fun getArticleList(num: Int): LiveData<NetResult<ArticleListEntity>> {
            // 需要具体业务实现
            throw RuntimeException("You must override this method!")
        }
            
        ... 省略部分代码 ...
    }
    
  3. BjnewsArticlesViewModel 中重写使用

    class BjnewsArticlesViewModel(
            private val repository: ArticleRepository
    ) : BaseViewModel(),
            ArticleCollectionInterface by ArticleCollectionInterfaceImpl(repository),
            ArticleListPagingInterface by ArticleListPagingInterfaceImpl() {
    
        /** 公众号 id */
        var bjnewsId = ""
        
        override fun getArticleList(num: Int): LiveData<NetResult<ArticleListEntity>> {
            val result = MutableLiveData<NetResult<ArticleListEntity>>()
                viewModelScope.launch {
                    try {
                        result.value = repository.getBjnewsArticles(bjnewsId, num)
                    } catch (throwable: Throwable) {
                        Logger.t("NET").e(throwable, "getArticleList")
                    }
                }
            return result
        }
    }
    
  4. 运行查看效果,然后你会发现每次获取数据都会抛出异常,重写的 getArticleList 方法并没有生效,这是为什么?

类委托实现原理

查看 Kotlin 对应的 Java 代码

kotlin 语法中很多都是 语法糖,为了能够更好的理解这些语法的规则和使用,我们可以阅读 kotlin 代码对应的 Java 代码,Kotlin 插件 也为我们提供了这样的功能:

sXe51H.md.png

​ 通过依次点击 Tools -> Koltin -> Show Kotlin Bytecode -> DecompileKotlin 插件 会为我们生成 BjnewsArticleViewModel.decompiled.java 文件,这个就是 BjnewsArticleViewModel.kt 对应的 Java 代码。

类委托的实现

​ 通过对 BjnewsArticleViewModel.decompiled.java 文件的查看,我们发现关键字 by 之后的具体实现对象在 java 中被声明成了 final 修饰的成员变量

变量声明

​ 并且在构造方法中对其进行了初始化

变量初始化

​ 接口中的方法实现实际上都是调用了对应对象的方法

方法重写

​ 所以 类委托 的实现实际就是 将接口中对应的方法、变量委托给对应的类实现

之前的问题

​ 那么我们回到之前的问题,为什么重写了的方法不起作用?

重写获取数据方法

​ 我们可以看到 getArticleList 方法已经是重写了的,但是追踪一下你会发现重写的这个方法并没有任何地方调用,当我们进行网络请求的时候,触发时起源于 ArticleListPagingInterface 中的 pageNumber 的变动,而由于我们使用了 类委托,在 BjnewsArticleViewModel 中实际进行刷新获取数据的调用的时代理对象 ArticleListPagingInterfaceImpl 中的方法,也就是说加载数据走的是代理对象里面的逻辑,而在 ArticleListPagingInterfaceImplgetArticleList 方法固定抛出异常,因此每次请求数据都会抛出异常。所以对于不同界面可能有的不同数据获取方式,我们选择了声明一个 lambda 对象用于存储获取数据的请求,在不同界面设置不同的获取方式。

因此,使用 类委托 我们确实可以达到 一个类继承多个类 的效果,但是我们需要知道的是这种方式终究不是继承,不能一味的按照继承的思路来实现。

总结

​ 最后,我们得出结论,使用 类委托 我们确实可以达到 一个类继承多个类 的效果,但是我们需要知道的是这种方式终究不是继承,不能一味的按照继承的思路来实现,需要注意以下几点:

  1. 如果一个 接口 中的方法被 委托类 中的其他方法调用,那么仅仅重写 实现类 中的方法是无效的,必须同时重写 委托类 中调用改方法的方法,或者将对应逻辑修改为对象实现。
  2. 基于上面一条,不管 委托类 中实现了多少个接口,添加了多少方法,对于 实现类 来说都是不可触及的,class A: B by BImpl() 中,不管 BImpl 有多少逻辑,对于 A 来说,关注的永远都只有 B 中声明的方法及变量。

​ 那么关于 Kotlin类委托 到这里就说完了,感谢大家的耐心观看,我是 WangJie0822 ,一个普普通通的程序猿,欢迎关注。

作者: WangJie0822
链接: http://www.wangjie0822.top/posts/438581be
来源: WangJie0822
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容