2017-03-12 97 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 
    } 
} 

希望這會幫助你。

相關問題