父类返回子类类型的函数写法

栏目: Scala · 发布时间: 5年前

内容简介:一看题目,有点儿晕。看个例子马上就明白了:我们有这么一个类,一看就是要写 Builder 模式。不过由于我们的这个 Event 的类型比较多,因此希望写一个父类,来一个子类感受下:看上去也没啥大毛病,用一下吧:

一看题目,有点儿晕。看个例子马上就明白了:

abstract class EventBuilder() {
    protected var retryLimit = 3

    fun retryLimit(retryLimit: Int): EventBuilder {
        this.retryLimit = retryLimit
        return this
    }

    abstract fun build(): PollingEvent
}

我们有这么一个类,一看就是要写 Builder 模式。不过由于我们的这个 Event 的类型比较多,因此希望写一个父类,来一个子类感受下:

class DisposableEventBuilder : EventBuilder() {
    private var delay: Long = 0L
    fun delay(delay: Long): DisposableEventBuilder {
        this.delay = delay
        return this
    }

    override fun build() = object: DisposableEvent(name, delay){
        override fun onDisposableEvent() {
            callback.onEvent(this)
        }
    }
}

看上去也没啥大毛病,用一下吧:

DisposableEventBuilder().retryLimit(3)
        .delay(60_000) // ERROR!! 
        .build()

我们调用完父类的 retryLimit 方法后,想要设置下 delay ,结果发现没有这个方法。

“我 X,这什么玩意儿”,你嘟囔了一句。

因为返回的是父类,所以链式调用掉链子了。这就尴尬了。

2. Scala 的解法

如果这段代码用 Scala 写,那么用 this.type 就简直完美的解决了这个问题:

abstract class SuperBuilder {
    private var retryLimit: Int = 0

    def retryLimit(retryLimit: Int): this.type = {
        this.retryLimit = retryLimit
        this
    }
}

class SubBuilder extends SuperBuilder {
    private var delay: Long = 0

    def delay(delay: Long): SubBuilder = {
        this.delay = delay
        this
    }
}

调用时:

new SubBuilder().retryLimit(3).delay(60000)

一点儿毛病都么有。

Kotlin 有这个特性吗?并没有。

3. Kotlin 的解法

Kotlin 倒也不是没有办法解决这个问题,用下泛型就好了:

abstract class EventBuilder<T : EventBuilder<T>>() {
    protected var retryLimit = 3

    fun retryLimit(retryLimit: Int): T {
        this.retryLimit = retryLimit
        return this as T
    }

    abstract fun build(): PollingEvent
}

这个泛型给父类加了一个泛型参数,这个参数则必须是当前类的子类,那么这样的话我们就可以在返回自身类型的位置返回 T 这个类型了。

子类的改动就很简单了,只需要给父类加一个泛型参数为自己的类型即可:

class DisposableEventBuilder : EventBuilder<DisposableEventBuilder>() {
     ...
}

其他的什么也不用动,这时候我们的链式调用就没啥问题了:

DisposableEventBuilder().retryLimit(3)
        .delay(60_000) // OK!!
        .build()

这一点上 Kotlin 和 Java 其实是一致的,所以你也可以用 Java 写出类似的代码:

abstract class SuperBuilder<T extends SuperBuilder<T>> {
    private int retryLimit = 0;

    T retryLimit(int retryLimit) {
        this.retryLimit = retryLimit;
        return (T) this;
    }
}

class SubBuilder extends SuperBuilder<SubBuilder> {
    private long delay = 0;

    SuperBuilder delay(long delay) {
        this.delay = delay;
        return this;
    }
}

好了,今天就先这样~~


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数字民主的迷思

数字民主的迷思

[美] 马修·辛德曼 / 唐杰 / 中国政法大学出版社 / 2015-12-25 / CNY 39.00

马修·辛德曼著的《数字民主的迷思》主要讨论互联网对美国政治的影响,聚焦的是“民主化”这一课题。针对公众关于网络民主的美好想象与过分狂热,它通过对在线竞选、链接结构、流量模式、搜索引擎使用、博客与博主、内容生产的“规模经济”等主题的深入处理,借助大量数据图表与分析,勾勒出互联网政治的种种局限性。尤其表明,网络政治信息仍然为一小群精英与机构所创造和过滤,在网络的每一个层次和领域都仍然遵循着“赢家通吃”......一起来看看 《数字民主的迷思》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具