如何在 kotlin 中使用 :: 调用带参数的静态方法
How call static method with params using :: in kotlin
想象一下我们需要在 kotlin 中使用 :: 调用带有参数的静态方法的情况。实际上我只能用没有参数的函数来做,例如
Base64::hashCode
但是当我尝试使用
Base64::encodeToString
然后我收到警告
Overload resolution ambiguity. All these functions match.
public open fun encodeToString(input: ByteArray!, flags: Int): String! defined in android.util.Base64
public open fun encodeToString(input: ByteArray!, offset: Int, len: Int, flags: Int): String! defined in android.util.Base64
编译器也不接受这种形式
(Base64::encodeToString)( byteArrayOf(2), Base64.DEFAULT)
我想使用 mockito 的新功能来模拟这个方法 here
感谢您提供任何信息!
::
语法非常有限,因为它不允许泛型类型参数和具有多个参数的方法。但是,没有什么能阻止您像这样传递 lambda 引用:
{ param ->
param.encodeToString()
}
一般来说,可调用引用语法不能与重载方法一起使用,因为编译器不知道您希望他选择什么变体(在这种情况下使用 2 or 4 参数)。
但这不是这里唯一的问题。
通过这种方式获得的实例类型为KFunction, which in parameterful case treated differently than function types (this is a well known, but still unfixed compiler bug).
因此,我认为您需要使用以下语法模拟 encodeToString
方法的两个重载变体(如果您想使用其中任何一个):
Mockito.mockStatic(Base64::class.java).use { theMock ->
theMock.`when`<Any> { Base64.encodeToString(any(), any()) }.thenReturn("MyMockString")
theMock.`when`<Any> { Base64.encodeToString(any(), any(), any(), any()) }.thenReturn("MyMockString")
assertEquals("MyMockString", Base64.encodeToString(byteArrayOf(), 111))
assertEquals("MyMockString", Base64.encodeToString(byteArrayOf(), 111, 111, 111))
}
另请注意 Mockito javadocs 说:
We recommend against mocking static methods of classes in the standard library
您可以显式指定类型,因此它知道您要引用哪个函数:
import kotlin.reflect.KFunction2
val encode: KFunction2<ByteArray, Int, ByteArray> = Base64::encode
其中KFunction2
表示它是一个2参数函数,ByteArray
和Int
是参数——最后一个ByteArray
是return类型.
::encode
是静态函数,所以只是处理调用时传入的参数。相比之下,hashcode()
是一个实例方法,所以即使 调用本身 不接受参数,该函数也会接受一个 Base64
实例(你的东西'正在调用 hashCode()
:
val hashCode: KFunction1<Base64, Int> = Base64::hashCode
(实例类型,return类型)
这基本上就是它的工作原理 - 您可以定义 encode
函数引用 val
并像往常一样调用它,参数提示将告诉您它知道它是哪个函数。
虽然不能保证它会适用于您正在做的任何事情!
想象一下我们需要在 kotlin 中使用 :: 调用带有参数的静态方法的情况。实际上我只能用没有参数的函数来做,例如
Base64::hashCode
但是当我尝试使用
Base64::encodeToString
然后我收到警告
Overload resolution ambiguity. All these functions match. public open fun encodeToString(input: ByteArray!, flags: Int): String! defined in android.util.Base64 public open fun encodeToString(input: ByteArray!, offset: Int, len: Int, flags: Int): String! defined in android.util.Base64
编译器也不接受这种形式
(Base64::encodeToString)( byteArrayOf(2), Base64.DEFAULT)
我想使用 mockito 的新功能来模拟这个方法 here
感谢您提供任何信息!
::
语法非常有限,因为它不允许泛型类型参数和具有多个参数的方法。但是,没有什么能阻止您像这样传递 lambda 引用:
{ param ->
param.encodeToString()
}
一般来说,可调用引用语法不能与重载方法一起使用,因为编译器不知道您希望他选择什么变体(在这种情况下使用 2 or 4 参数)。 但这不是这里唯一的问题。
通过这种方式获得的实例类型为KFunction, which in parameterful case treated differently than function types (this is a well known, but still unfixed compiler bug).
因此,我认为您需要使用以下语法模拟 encodeToString
方法的两个重载变体(如果您想使用其中任何一个):
Mockito.mockStatic(Base64::class.java).use { theMock ->
theMock.`when`<Any> { Base64.encodeToString(any(), any()) }.thenReturn("MyMockString")
theMock.`when`<Any> { Base64.encodeToString(any(), any(), any(), any()) }.thenReturn("MyMockString")
assertEquals("MyMockString", Base64.encodeToString(byteArrayOf(), 111))
assertEquals("MyMockString", Base64.encodeToString(byteArrayOf(), 111, 111, 111))
}
另请注意 Mockito javadocs 说:
We recommend against mocking static methods of classes in the standard library
您可以显式指定类型,因此它知道您要引用哪个函数:
import kotlin.reflect.KFunction2
val encode: KFunction2<ByteArray, Int, ByteArray> = Base64::encode
其中KFunction2
表示它是一个2参数函数,ByteArray
和Int
是参数——最后一个ByteArray
是return类型.
::encode
是静态函数,所以只是处理调用时传入的参数。相比之下,hashcode()
是一个实例方法,所以即使 调用本身 不接受参数,该函数也会接受一个 Base64
实例(你的东西'正在调用 hashCode()
:
val hashCode: KFunction1<Base64, Int> = Base64::hashCode
(实例类型,return类型)
这基本上就是它的工作原理 - 您可以定义 encode
函数引用 val
并像往常一样调用它,参数提示将告诉您它知道它是哪个函数。
虽然不能保证它会适用于您正在做的任何事情!