Kotlin 的静态扩展方法

如何在 Kotlin 定义静态扩展方法?这有可能吗?我目前有一个扩展方法,如下所示。

public fun Uber.doMagic(context: Context) {
// ...
}

可以对实例调用上述扩展。

uberInstance.doMagic(context) // Instance method

但是如何使用静态方法,如下所示。

Uber.doMagic(context)         // Static or class method
59326 次浏览

您可以创建一个静态方法,并使用如下对象:

class Foo {
// ...
companion object {
public fun bar() {
// do anything
}
}
}

然后你可以这样称呼它:

class Baz {
// ...
private fun callBar() {
Foo.bar()
}
}

要实现 Uber.doMagic(context),您可以编写 Uber同伴物体的扩展(需要同伴对象声明) :

class Uber {
companion object {}
}


fun Uber.Companion.doMagic(context: Context) { }

我也非常喜欢在 Kotlin 添加静态扩展方法的可能性。作为一个解决方案,现在我将向多个类添加扩展方法,而不是在所有类中使用一个静态扩展方法。

class Util


fun Util.isDeviceOnline(context: Context): Boolean {
val connMgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connMgr.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected
}


fun Activity.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }
fun OkHttpClient.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }

官方文件是这样写的:

为包级函数生成静态方法 中定义的函数也可以生成静态方法 如果将这些函数注释为 @ Jvmstatic 例如:

Kotlin 静态方法

class C {
companion object {
@JvmStatic fun foo() {}
fun bar() {}
}
}

现在,foo ()在 Java 中是静态的,而 bar ()不是:

C.foo(); // works fine
C.bar(); // error: not a static method

建议你看看 这个链接。正如您所看到的,您只需要在包(文件)的顶层声明方法:

package strings
public fun joinToString(...): String { ... }

这等于

package strings;


public class JoinKt {
public static String joinToString(...) { ... }
}

对于 Constans 一切都是一样的,这个声明

val UNIX_LINE_SEPARATOR = "\n"

等于

public static final String UNIX_LINE_SEPARATOR = "\n";

实际上30分钟前我就有这个问题了,所以我开始四处寻找,但是找不到任何解决方案或者变通方法,但是在搜索的时候我在 Kotlinglang 的网站上找到了 这部分,上面写着:

请注意,可以使用可为空的接收方类型定义扩展。即使对象变量的值为空,也可以对其调用这样的扩展。

所以我有了一个最疯狂的想法,为什么不定义一个可以为空的接收器的扩展函数(实际上没有使用该接收器) ,然后在一个空对象上调用它! 所以我试了试,效果不错,但是看起来太丑了,就像这样:

(null as Type?).staticFunction(param1, param2)

所以我在接收方类型的扩展文件中创建了一个值为 null 的 val,然后在我的其他类中使用它。 因此,作为一个例子,下面是我如何在 Android 中为 Navigation类实现一个“静态”扩展函数: 在我的 NavigationExtensions.kt 文件中:

val SNavigation: Navigation? = null
fun Navigation?.createNavigateOnClickListener(@IdRes resId: Int, args: Bundle? = null, navOptions: NavOptions? = null,
navigationExtras: Navigator.Extras? = null) : (View) -> Unit {
//This is just implementation details, don't worry too much about them, just focus on the Navigation? part in the method declaration
return { view: View -> view.navigate(resId, args, navOptions, navigationExtras) }
}

在使用它的代码中:

SNavigation.createNavigateOnClickListener(R.id.action_gameWonFragment_to_gameFragment)

显然,这不是一个类名,它只是一个具有空值的类类型变量。在扩展制造者方面(因为他们必须创建变量)和开发者方面(因为他们必须使用 SType格式而不是实际的类名) ,这显然是丑陋的,但是与实际的静态函数相比,这是目前可以实现的最接近的。希望 Kotlin 语言制造商能够响应创建的 问题,并在语言中添加这个特性。

要在 kotlin 中创建扩展方法,您必须创建一个 kotlin 文件(而不是类) ,然后在该文件中声明您的方法 例如:

public fun String.toLowercase(){
// **this** is the string object
}

导入正在处理的类或文件中的函数并使用它。

因为我一直遇到这个时,搜索,这里有一个不同的方法,我没有看到任何人提到,工程在一个静态的方式 还有它与泛型!

扩展定义:

// Extension function
fun <T> KClass<T>.doSomething() = /* do something */


// Extension Property
val <T> KClass<T>.someVal get() = /* something */

用法:

MyType::class.doSomething()


MyType::class.someVal

正如您所看到的,技巧是将扩展函数附加到类型的 KClass,因为它可以被静态引用。

我还需要能够用静态方法扩展一个 Java 对象,发现对我来说最好的解决方案是创建一个 Kotlin 对象来扩展 Java 类并在那里添加我的方法。

object Colour: Color(){
fun parseColor(r: Int?, g: Int?, b: Int?) = parseColor(String.format("#%02x%02x%02x", r, g, b))
}

祈求:

val colour = Colour.parseColor(62, 0, 100)