Kotlin 适配器模式:getter 函数上的重复方法名称错误
Kotlin adapter pattern: Duplicate method name error on getter function
只是简单的 kotlin 代码来演示四人组设计模式中的适配器模式。我今天有一个关于这个的演讲,但我做不到。好难过。我不想添加太多细节,但他们不允许我在没有太多细节的情况下 post。
异常:
Exception in thread "main" java.lang.ClassFormatError: Duplicate method name "getRadius" with signature "()I" in class file RoundHole
at java.lang.ClassLoader.defineClass1 (ClassLoader.java:-2)
at java.lang.ClassLoader.defineClass (ClassLoader.java:756)
at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:142)
代码:
interface WorkingWithRound {
fun getRadius(): Int
}
open class RoundPeg(val radius: Int = 0): WorkingWithRound {
override fun getRadius() = radius
}
class RoundHole(val radius: Int = 0): WorkingWithRound {
override fun getRadius() = radius
fun fit(peg: RoundPeg) {
println(getRadius() >= peg.getRadius())
}
}
class SquarePeg(val width: Int = 0)
class SquarePegAdapter(val speg: SquarePeg): RoundPeg() {
override fun getRadius() = (speg.width / 2 * 1.4).toInt()
}
fun main() {
val hole = RoundHole(5)
val rpeg = RoundPeg(5)
hole.fit(rpeg)
val small_sqpeg = SquarePeg(5)
val large_sqpeg = SquarePeg(10)
//hole.fit(small_sqpeg) // this won't compile (incompatible types)
val small_sqpeg_adapter = SquarePegAdapter(small_sqpeg)
val large_sqpeg_adapter = SquarePegAdapter(large_sqpeg)
hole.fit(small_sqpeg_adapter) // true
hole.fit(large_sqpeg_adapter) // false
}
Kotlin 为实例变量生成 getter 方法,因此出现错误。解决问题的几个选项
- 将
radius
变量设为私有
open class RoundPeg(private val radius: Int = 0): WorkingWithRound
- 用
@JvmField
标记radius
指示编译器不要生成任何getter
class RoundHole(@JvmField val radius: Int = 0): WorkingWithRound
我认为如果接口定义 property 而不是 getter 方法,这会更简单(同时避免编译问题):
interface WorkingWithRound {
val radius: Int
}
编译成几乎相同的字节码;但意图更明确,然后可以直接在构造函数中实现:
open class RoundPeg(override val radius: Int = 0): WorkingWithRound
class RoundHole(override val radius: Int = 0): WorkingWithRound {
fun fit(peg: RoundPeg) {
println(radius >= peg.radius)
}
}
SquarePegAdapter 可以简化,因为它不再需要存储 speg
值,但可以简单地将其用作 属性:
的初始化程序
class SquarePegAdapter(speg: SquarePeg): RoundPeg() {
override val radius = (speg.width / 2 * 1.4).toInt()
}
其余代码无需更改。
只是简单的 kotlin 代码来演示四人组设计模式中的适配器模式。我今天有一个关于这个的演讲,但我做不到。好难过。我不想添加太多细节,但他们不允许我在没有太多细节的情况下 post。
异常:
Exception in thread "main" java.lang.ClassFormatError: Duplicate method name "getRadius" with signature "()I" in class file RoundHole
at java.lang.ClassLoader.defineClass1 (ClassLoader.java:-2)
at java.lang.ClassLoader.defineClass (ClassLoader.java:756)
at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:142)
代码:
interface WorkingWithRound {
fun getRadius(): Int
}
open class RoundPeg(val radius: Int = 0): WorkingWithRound {
override fun getRadius() = radius
}
class RoundHole(val radius: Int = 0): WorkingWithRound {
override fun getRadius() = radius
fun fit(peg: RoundPeg) {
println(getRadius() >= peg.getRadius())
}
}
class SquarePeg(val width: Int = 0)
class SquarePegAdapter(val speg: SquarePeg): RoundPeg() {
override fun getRadius() = (speg.width / 2 * 1.4).toInt()
}
fun main() {
val hole = RoundHole(5)
val rpeg = RoundPeg(5)
hole.fit(rpeg)
val small_sqpeg = SquarePeg(5)
val large_sqpeg = SquarePeg(10)
//hole.fit(small_sqpeg) // this won't compile (incompatible types)
val small_sqpeg_adapter = SquarePegAdapter(small_sqpeg)
val large_sqpeg_adapter = SquarePegAdapter(large_sqpeg)
hole.fit(small_sqpeg_adapter) // true
hole.fit(large_sqpeg_adapter) // false
}
Kotlin 为实例变量生成 getter 方法,因此出现错误。解决问题的几个选项
- 将
radius
变量设为私有
open class RoundPeg(private val radius: Int = 0): WorkingWithRound
- 用
@JvmField
标记radius
指示编译器不要生成任何getter
class RoundHole(@JvmField val radius: Int = 0): WorkingWithRound
我认为如果接口定义 property 而不是 getter 方法,这会更简单(同时避免编译问题):
interface WorkingWithRound {
val radius: Int
}
编译成几乎相同的字节码;但意图更明确,然后可以直接在构造函数中实现:
open class RoundPeg(override val radius: Int = 0): WorkingWithRound
class RoundHole(override val radius: Int = 0): WorkingWithRound {
fun fit(peg: RoundPeg) {
println(radius >= peg.radius)
}
}
SquarePegAdapter 可以简化,因为它不再需要存储 speg
值,但可以简单地将其用作 属性:
class SquarePegAdapter(speg: SquarePeg): RoundPeg() {
override val radius = (speg.width / 2 * 1.4).toInt()
}
其余代码无需更改。