首页 > 解决方案 > 很好地将家务代码委托给超类?

问题描述

我有两节课:

画布元素

abstract class CanvasElement(
    var posX: Double = 0.0,
    var posY: Double = 0.0,
    var fillStyle: String = "",
    var strokeStyle: String = "",
    var shadowColor: String = "",
    var shadowBlur: String = "",
    var shadowOffsetX: Double = 0.0,
    var shadowOffsetY: Double = 0.0,
    var context: CanvasRenderingContext2D? = null) {

constructor(posX: Double, posY: Double) : this() {
    this.posX = posX
    this.posY = posY
}

fun registerWithContext() {
    this.context = this.context
}

fun move(onXaxis: Double, onYaxis: Double) {
    this.posX = posX + onXaxis
    this.posY = posY + onYaxis
}


fun drawOnCanvasContext(drawFunctionOfElement: Unit) {
    this.context?.beginPath();
}

fun prepareContext() {
    this.context?.beginPath();
}

fun finishDrawingOn() {
    this.context?.fillStyle = this.fillStyle
    this.context?.strokeStyle = this.strokeStyle
    this.context?.shadowColor = shadowColor
    this.context?.save()
    this.context?.stroke()
    this.context?.fill()
}

fun setFillStyle(fillStyle: String) {

}

abstract fun drawOnContext()
}

圆圈

class Circle(var radius : Double = 0.0,
        posX : Double,
        posY : Double,
        fillStyle : String,
        strokeStyle : String,
        shadowColor : String,
        shadowBlur : String,
        shadowOffsetX : Double,
        shadowOffsetY : Double,
        context : CanvasRenderingContext2D) : CanvasElement(posX = posX, posY = posY, fillStyle = fillStyle, strokeStyle = strokeStyle, shadowColor = shadowColor, shadowOffsetX = shadowOffsetX, shadowOffsetY = shadowOffsetY, context = context ){

constructor(posX: Double,
            posY: Double,
            radius: Double,
            strokeStyle: String,
            fillStyle: String,
            context: CanvasRenderingContext2D) : this(posX = posX, posY = posY, radius = radius, fillStyle = fillStyle, strokeStyle = strokeStyle, shadowColor = "", shadowBlur = "", shadowOffsetX = 0.0, shadowOffsetY = 0.0, context = context)

override fun drawOnContext(){
    prepareContext()
    context?.arc(posX, this.posY, this.radius,0.0,2 * kotlin.math.PI)
    finishDrawingOn()
}
}

如您所见,Circle 覆盖了抽象 fun drawOnContext() (CanvasElement 的其他子类,如 Rectangle 等),它们在context?...内部的调用中有所不同drawOnContext()

问题: 但目前,CanvasElement 的每个新子类都必须调用管家功能prepareContext()finishDrawingOn()而且很容易忘记实现这一点。我想摆脱这种冗余。

如何将这些实现委托给超类?

标签: inheritancekotlin

解决方案


在 CanvasElement 中,替换

abstract fun drawOnContext()
}

fun drawOnContext()
    prepareContext()
    onDraw()
    finishDrawingOn()
}

abstract protected fun onDraw()

然后在你的子类中:

override protected fun onDraw(){
    context?.arc(posX, this.posY, this.radius,0.0,2 * kotlin.math.PI)
}

虽然,我可能会通过消除冗余函数和许多 null 安全调用来简化它:

fun drawOnContext()
    context?.apply{
        beginPath()
        onDraw(this)
        fillStyle = this@CanvasElement.fillStyle
        strokeStyle = this@CanvasElement.strokeStyle
        shadowColor = this@CanvasElement.shadowColor
        save()
        stroke()
        fill()
    }
}

abstract protected fun onDraw(context: Context)

推荐阅读