标题似乎不清楚,这是一个完整的句子?【具体标题见下】


#1

标题内容:Java转换为Kotlin问题:我在尝试改写MyBatisPlus的Java代码为Kotlin代码的时候,出现这个问题如何改?

总是提示:“标题似乎不清楚,这是一个完整的句子?”,这个怎么办!?

比如该类:https://github.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/AbstractChainWrapper.java
转换出来的代码如下所示【Intellij可以直接转】,但是出现如图的提示错误,很奇怪的问题,这仅仅是一个例子,还有好几个,头痛了2天,感觉泛型复杂点,kotlin就不兼容了:
代码如下:

abstract class AbstractChainWrapper<T, R, Children : AbstractChainWrapper<T, R, Children, Param>?, Param>
    : Wrapper<T>(), Compare<Children, R>, Func<Children, R>, Join<Children>, Nested<Param, Children> {
    protected val typedThis = this as Children
    /**
     * 子类所包装的具体 Wrapper 类型
     */
    protected var wrapperChildren: Param? = null

    open val wrapper: AbstractWrapper<*, *, *>?
        get() = wrapperChildren as AbstractWrapper<*, *, *>?

    override fun getEntity(): T {
        throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getEntity")
    }

    override fun getExpression(): MergeSegments {
        throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getExpression")
    }

    override fun getCustomSqlSegment(): String {
        throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getCustomSqlSegment")
    }

    override fun <V> allEq(condition: Boolean, params: Map<R, V>, null2IsNull: Boolean): Children {
        wrapper.allEq(condition,params,null2IsNull)
        return typedThis
    }

    override fun <V> allEq(condition: Boolean, filter: BiPredicate<R, V>, params: Map<R, V>, null2IsNull: Boolean): Children {
        wrapper!!.allEq(condition, filter, params, null2IsNull)
        return typedThis
    }

    override fun eq(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.eq(condition, column, `val`)
        return typedThis
    }

    override fun ne(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.ne(condition, column, `val`)
        return typedThis
    }

    override fun gt(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.gt(condition, column, `val`)
        return typedThis
    }

    override fun ge(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.ge(condition, column, `val`)
        return typedThis
    }

    override fun lt(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.lt(condition, column, `val`)
        return typedThis
    }

    override fun le(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.le(condition, column, `val`)
        return typedThis
    }

    override fun between(condition: Boolean, column: R, val1: Any, val2: Any): Children {
        wrapper!!.between(condition, column, val1, val2)
        return typedThis
    }

    override fun notBetween(condition: Boolean, column: R, val1: Any, val2: Any): Children {
        wrapper!!.notBetween(condition, column, val1, val2)
        return typedThis
    }

    override fun like(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.like(condition, column, `val`)
        return typedThis
    }

    override fun notLike(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.notLike(condition, column, `val`)
        return typedThis
    }

    override fun likeLeft(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.likeLeft(condition, column, `val`)
        return typedThis
    }

    override fun likeRight(condition: Boolean, column: R, `val`: Any): Children {
        wrapper!!.likeRight(condition, column, `val`)
        return typedThis
    }

    override fun isNull(condition: Boolean, column: R): Children {
        wrapper!!.isNull(condition, column)
        return typedThis
    }

    override fun isNotNull(condition: Boolean, column: R): Children {
        wrapper!!.isNotNull(condition, column)
        return typedThis
    }

    override fun `in`(condition: Boolean, column: R, coll: Collection<*>?): Children {
        wrapper.`in`(condition, column, coll)
        return typedThis
    }

    override fun notIn(condition: Boolean, column: R, coll: Collection<*>?): Children {
        wrapper.notIn(condition, column, coll)
        return typedThis
    }

    override fun inSql(condition: Boolean, column: R, inValue: String): Children {
        wrapper!!.inSql(condition, column, inValue)
        return typedThis
    }

    override fun notInSql(condition: Boolean, column: R, inValue: String): Children {
        wrapper!!.notInSql(condition, column, inValue)
        return typedThis
    }

    override fun groupBy(condition: Boolean, vararg columns: R): Children {
        wrapper.groupBy(condition, *columns)
        return typedThis
    }

    override fun orderBy(condition: Boolean, isAsc: Boolean, vararg columns: R): Children {
        wrapper!!.orderBy(condition, isAsc, *columns)
        return typedThis
    }

    override fun having(condition: Boolean, sqlHaving: String, vararg params: Any): Children {
        wrapper!!.having(condition, sqlHaving, *params)
        return typedThis
    }

    override fun or(condition: Boolean): Children {
        wrapper!!.or(condition)
        return typedThis
    }

    override fun apply(condition: Boolean, applySql: String, vararg value: Any): Children {
        wrapper!!.apply(condition, applySql, *value)
        return typedThis
    }

    override fun last(condition: Boolean, lastSql: String): Children {
        wrapper!!.last(condition, lastSql)
        return typedThis
    }

    override fun comment(condition: Boolean, comment: String): Children {
        wrapper!!.comment(condition, comment)
        return typedThis
    }

    override fun exists(condition: Boolean, existsSql: String): Children {
        wrapper!!.exists(condition, existsSql)
        return typedThis
    }

    override fun notExists(condition: Boolean, notExistsSql: String): Children {
        wrapper!!.notExists(condition, notExistsSql)
        return typedThis
    }

    override fun and(condition: Boolean, consumer: Consumer<Param>): Children {
        wrapper!!.and(condition, consumer)
        return typedThis
    }

    override fun or(condition: Boolean, consumer: Consumer<Param>): Children {
        wrapper!!.or(condition, consumer)
        return typedThis
    }

    override fun nested(condition: Boolean, consumer: Consumer<Param>): Children {
        wrapper!!.nested(condition, consumer)
        return typedThis
    }

    override fun getSqlSegment(): String {
        throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getSqlSegment")
    }
}

图片如下:


#2

问题在这一行:

open val wrapper: AbstractWrapper<*, *, *>?
        get() = wrapperChildren as AbstractWrapper<*, *, *>?

这里返回的 AbstractWrapper 没有任何泛型信息,自然会导致调用 allEq 函数的时候对应的参数的类型成为 Nothing,导致你无法调用,改成这样就好了:

open val wrapper: AbstractWrapper<T, R, *>?
        get() = wrapperChildren as AbstractWrapper<T, R, *>?

#3

真要把锅扔给谁的话,也是这段 Java 代码的原作者的锅,为了省事,该指定泛型参数的地方不指定,非要用 raw type,一个 @SuppressWarnings("unchecked") 把问题掩盖过去,怪不到 Kotlin 头上


#4

哈哈,是的,我还有问题,请教大神。我这么改了后,发现后面的BUG还是存在这个BUG,请问如何改?


#5

这是因为 AbstractWrapper<T, R, *> 还是不够,最后一个类型参数还是没写出来,我对 Mybatis Plus 的代码不了解,你可以研究一下这个类型参数是什么,把它补充上去就可以了

第三个类型参数好像是 Children?你可以试一下


#6

MP这个地方的源码很怪异,请看图


图中的C的类型是自己,这下尴尬了,如果不用*号,就会出现图中的问题。


#7

因为这里的 AbstractChainWrapper 并没有继承 AbstractWrapper,所以 C 只是 AbstractChainWrapper的子类,而不是 AbstractWrapper 的子类,所以不能把它作为 AbstractWrapper 的第三个类型参数

所以要改的话,不要直接实现 Wrapper 接口,改为继承 AbstractWrapper 就好了


#8

这里我感觉 Mybatis Plus 的代码可能有些问题,C 确实不是 AbstractWrapper 的子类型,把它作为 AbstractWrapper 的第三个类型参数肯定是不行的

然而作者干脆就直接使用了 raw type,一个 @SuppressWarnings("unchecked") 把问题掩盖过去,感觉迟早会是一个坑

所以啊,都用 Kotlin 了,为什么还执着于 Mybatis 呢?人生苦短,试试 Ktorm 吧:grinning:


#9

哈哈,Ktorm 很好,新项目会选择他的!


#10

说到这个,我感觉Kotlin对类型的要求比Java更严格!!


#11

说得对。严格一些,避免写出bug,自己很难发现的那种


#12

标题的问题我回头看下,这个我的暂时没太搞明白他的校验机制


京ICP备16022265号-2 Kotlin China 2017 - 2018