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

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

内容简介:一看题目,有点儿晕。看个例子马上就明白了:我们有这么一个类,一看就是要写 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;
    }
}

好了,今天就先这样~~


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

查看所有标签

猜你喜欢:

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

An Introduction to Genetic Algorithms

An Introduction to Genetic Algorithms

Melanie Mitchell / MIT Press / 1998-2-6 / USD 45.00

Genetic algorithms have been used in science and engineering as adaptive algorithms for solving practical problems and as computational models of natural evolutionary systems. This brief, accessible i......一起来看看 《An Introduction to Genetic Algorithms》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具