Kotlin中的静态扩展方法

时间:2015-01-29 08:35:24

标签: static-methods kotlin

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

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

可以在实例上调用上述扩展名。

uberInstance.doMagic(context) // Instance method

但我如何制作如下所示的静态方法。

Uber.doMagic(context)         // Static or class method

9 个答案:

答案 0 :(得分:105)

要实现Uber.doMagic(context),您可以编写Uber的{​​{3}}扩展名(需要配套对象声明):

class Uber {
    companion object {}
}

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

答案 1 :(得分:9)

这是官方文件所说的:

  

Kotlin为包级函数生成静态方法。科特林   也可以为named中定义的函数生成静态方法   对象或伴随对象,如果您将这些函数注释为   @JvmStatic。例如:

Kotlin static methods

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

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

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

答案 2 :(得分:5)

您可以使用Companion对象创建静态方法,如:

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

然后你可以这样称呼它:

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

答案 3 :(得分:1)

由于我在搜索时不断遇到这种情况,因此这是另一种方法,我还没有看到有人提到它以静态方式起作用,而 可以与泛型一起使用!

扩展定义:

// 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上,因为可以静态引用该扩展功能。

答案 4 :(得分:0)

建议您查看this链接。正如您在那里看到的那样,您应该在包(文件)的顶层声明方法:

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";

答案 5 :(得分:0)

我实际上是在30分钟前提出了这个确切的问题,所以我开始四处搜寻,但找不到任何解决方案或解决方法,但是在Kotlinglang网站上搜索this section时发现:

  

请注意,可以使用可为空的接收器类型定义扩展。即使对象变量的值为null,也可以对其进行扩展。

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

(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语言制作者将对所创建的issue做出回应,并在该语言中添加该功能。

答案 6 :(得分:0)

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

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

将功能导入您正在使用的类或文件中并使用它。

答案 7 :(得分:0)

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

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)

答案 8 :(得分:-2)

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

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) }