2017-03-12 32 views
5

下面是一个说明问题的一个小例子:如何从定义类的外部调用扩展方法?

abstract class Base { 
    abstract fun String.extension(x: Char) 
} 

class Derived : Base() { 
    override fun String.extension(x: Char) { 
     // Calling lots of methods on String, hence extension method 
     println("${first()} $length ${last()} ${firstOrNull { it == x }} ...") 
    } 
} 

从Java调用扩展方法很简单:

Base o = new Derived(); 
o.extension("hello world", 'l'); 

但我无法弄清楚如何做到这一点的纯科特林。 StringBase都没有extension方法。

回答

8

首先,请注意,定义为一个部件的延伸功能需要两个接收器,一个是封闭类的实例(调度接收机,通常是封闭类的this),另一个是实例功能扩展的类型(扩展接收器)。这记录在here

因此,要从课堂外调用这样的功能,您必须提供两个接收器。科特林doesn't have any syntax做明确像(x, "abc").stringExtension(),但您可以提供调度接收器隐含使用extension lambda

class C(val name: String) { 
    fun String.extended() = this + " extended by " + name 
} 

fun main(args: Array<String>) { 
    val c = C("c") 
    with(c) { println("abc".extended()) } 
} 

(runnable demo of this code)

with(...) { ... }块,c成为隐式接收器,从而使您可以将其用作C成员扩展程序中的调度接收器。这与使用功能类型与接收器的其他功能工作:applyrunuse

在你的情况,这将是with(o) { "hello world".extension('l') }

由于@KirillRakhman指出,扩展功能的扩展接收机C也可以被隐用作内部C定义的扩展调度接收机:

fun C.someExtension() = "something".extended() 
+0

您可以添加该扩展_functions_也工作。 –

+0

@KirillRakhman,没有明白,你能解释一下吗? – hotkey

+1

我的意思是,不仅可以使用扩展_lambdas_,而且可以使用扩展_functions_来提供隐式接收器。例如:'fun C.inScope()=“”.extended()' –

0

您的扩展功能仅在Base/Derived类中定义。见Declaring Extensions as Members

abstract class Base { 
    abstract fun String.extension(x: Char) 
} 

class Derived : Base() { 
    override fun String.extension(x: Char) { 
     // Calling lots of methods on String, hence extension method 
     println("${first()} $length ${last()} ${firstOrNull { it == x }} ...") 
    } 

    fun callExtension(c: Char) { 
     "hello".extension(c) 
    } 
} 

fun main(args: Array<String>) { 
    val base = Derived() 
    base.callExtension('h') 
} 
+1

实际上有一种方法可以从类之外调用* public *成员扩展:使用该类的隐式接收器实例。 – hotkey

0

要使用它decale类的外部的扩展方法,你应该实现它在类中,你应该这样做:

package com.sample.test 

import java.io.File 

fun File.folderLength() : Long { 
    return 0L 
} 

因此,在你的类调用这个方法:

package com.sample.util 

import com.sample.test.* 
import java.io.File 

class foo{ 
    fun getFolderSize(url: String) : Long{ 
     var file = new File("...") 
     var length = file.folderLength() 
     return length 
    } 
} 

希望这会帮助你。