鍍金池/ 問答/網(wǎng)絡(luò)安全/ Kotlin 可以動態(tài)為對象綁定一個額外對象嗎?

Kotlin 可以動態(tài)為對象綁定一個額外對象嗎?

我有一個方法,每次都必須傳入一個固定的對象 paint,因為這個函數(shù)會被頻繁調(diào)用,所以我不能在內(nèi)聯(lián)函數(shù)中創(chuàng)建對象。

inline fun Canvas.drawPoint(
    point: PointF,
    paint: Paint) {

    drawPoint(point.x, point.y, paint)
}

但是我很多地方都會調(diào)用這個方法。

          //(Canvas.apply(..,..))
            drawPoint(pointA, pointPaint)
            drawPoint(pointB, pointPaint)
            drawPoint(pointC, pointPaint)
            drawPoint(pointD, pointPaint)

可以看到每次都會傳入一個pointPaint對象。
所以我在想有沒有類似這樣一個功能

        //(Canvas.apply(..,..))
            bind(pointPaint)
            drawPoint(pointA)
            drawPoint(pointB)
            drawPoint(pointC)
            drawPoint(pointD)
回答
編輯回答
青瓷

完美符合你要求的方式肯定是沒有的,因為 bind 函數(shù)不可能改變另一個函數(shù)內(nèi)部的局部變量。

折中的方式也有很多,比如定義一個包級屬性:

var drawPaint: Paint? = null

然后原來的函數(shù)改為:

inline fun Canvas.drawPoint(
    point: PointF,
    paint: Paint) {

    paint?.let {
        drawPoint(point.x, point.y, it)
    }
}

方便使用還可以再定義一個函數(shù)來確保 drawPaint 能被準(zhǔn)確的賦值和釋放:

fun bindPaint(paint: Paint, action: () -> Unit) {
    drawPaint = paint
    action()
    drawPaint = null
}

這樣使用時就是:

// Canvas().apply {
bindPaint(somePaint) {
    drawPoint(x, y)
}

還有一種方式是定義一個包裝類,并在其中定義一個包含帶接收者 Lambda 表達式的參數(shù)的函數(shù)(接收者為 Canvas),然后將擴展函數(shù)定義到這個類中:

class PointPainter(private val paint: Paint) {
    fun Canvas.drawPoint(rect: RectF) {
        drawPoint(rect.x, rect.y, paint)
    }
}

然后定義含有接收者為這個包裝對象 Lambda 參數(shù)的函數(shù):

fun bindPointPainter(paint: Paint, drawAction: PointPainter.() -> Unit) {
    PointPainter(paint).drawAction()
}

這樣用時更方便一些:

// in canvas.apply block
bindPointPainter(somePaint) {
    drawPoint(rect1)
    drawPoint(rect2)
    // ...
}
2017年4月15日 23:45
編輯回答
墻頭草
    fun test() {
        Canvas().bindPaintDrawPoints(Paint())(
            arrayOf(PointF(1f, 2f),
                PointF(2f, 2f),
                PointF(3f, 2f),
                PointF(4f, 2f))
        )
    }

    fun Canvas.bindPaintDrawPoints(paint: Paint): (Array<PointF>) -> Unit {
        return {
            drawPoints(paint, it)
        }
    }

    fun Canvas.drawPoints(paint: Paint, points: Array<PointF>) {
        for (p in points) {
            this.drawPoint(p.x, p.y, paint)
        }
    }

2018年4月23日 04:48