iextensionunit类_如何在Kotlin中编写强类型泛型扩展函数?

Focus on the strong and generic parts.

Let's say I have this extension function:

fun Collection.myContains(item: E) : Boolean {

// quite pointless, I know, but a simple example

return item in this

}

the intention is to write a function that only accepts types of the collection elements (E), but this is not validated by the compiler?!

val isItInside: Boolean = listOf(1, 2).myContains("1")

happily compiles. My guess is that E is inferred to be Any.

How can I enforce this restriction within the Kotlin type system/generics?

(Kotlin version 1.3.41)

Original context

An exercise to try to write a small assertion framework. A bit more complicated, but tried to get the simplest repro above.

class Asserter(val value: T)

infix fun T.should(block: Asserter.() -> Unit) =

Asserter(this).block()

fun > Asserter.haveSize(size: Int) {

check(this.value.size == size) {

"expecting ${this.value} to be of size $size"

}

}

fun > Asserter.contain(item: E) {

check(item in this.value) {

"$item does not exist in $item"

}

}

class ShouldTest {

@Test fun intList() {

listOf(1, 2) should {

haveSize(2)

contain(1)

contain("2") // this shouldn't compile

}

}

@Test fun stringList() {

listOf("1", "2") should {

haveSize(2)

contain(1) // this shouldn't compile

contain("2")

}

}

}

解决方案

This appears to be due to the variance on the Collection interface's parameter, which is defined as Collection.

This means that Collection is a supertype of Collection, and so (apparently) the Collection.myContains() extension can be called on a Collection.

You can confirm this by replacing it with the invariant MutableCollection (and also the listOf() with mutableListOf()); you then get the compile-time ‘Type mismatch’ error as expected.

This surprised me, though.  I guess the compiler must infer E using both the receiver type and the parameter type.  (Can anyone confirm this?)  And, as you point out, it has the annoying effect of preventing stricter type-safety.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值