サーチ…


構文

  • fun TypeName.extensionName(params、...){/ * body * /} //宣言
  • あなたはジェネリックスを使って宣言することができます。<T> Any> TypeNameWithGenerics <T> .extensionName(params、...){/ * body * /} // Generics
  • myObj.extensionName(args、...)//呼び出し

備考

拡張機能は静的に解決されます。つまり、使用する拡張メソッドは、アクセスする変数の参照型によって決まります。実行時に変数の型が何であるかは関係ありません。同じ拡張メソッドが常に呼び出されます。これは、拡張メソッドを宣言しても、実際には受信者タイプにメンバーが追加されないためです。

トップレベルの拡張機能

最上位の拡張メソッドは、クラス内には含まれていません。

fun IntArray.addTo(dest: IntArray) {
    for (i in 0 .. size - 1) {
        dest[i] += this[i]
    }
}

上記の拡張メソッドは、 IntArrayIntArray定義されています。拡張メソッドが定義されているオブジェクト( 受信者と呼ばれる)には、キーワードthisを使用してアクセスすることに注意してください。

この拡張は次のように呼び出すことができます:

val myArray = intArrayOf(1, 2, 3)
intArrayOf(4, 5, 6).addTo(myArray)

潜在的な落とし穴:拡張機能が静的に解決される

呼び出される拡張メソッドは、アクセスされる変数の参照型に基づいてコンパイル時に決定されます。実行時に変数の型が何であるかは関係ありません。同じ拡張メソッドが常に呼び出されます。

open class Super

class Sub : Super()

fun Super.myExtension() = "Defined for Super"

fun Sub.myExtension() = "Defined for Sub"

fun callMyExtension(myVar: Super) {
    println(myVar.myExtension())
}

callMyExtension(Sub())

上記の例では、印刷され"Defined for Super"変数の宣言された型ため、 myVarあるSuper

人間が読める文字列をレンダリングするために長く伸びるサンプル

人間が読める文字列を描画するために、 Int型またはLong型の値があれば、

fun Long.humanReadable(): String {
    if (this <= 0) return "0"
    val units = arrayOf("B", "KB", "MB", "GB", "TB", "EB")
    val digitGroups = (Math.log10(this.toDouble())/Math.log10(1024.0)).toInt();
    return DecimalFormat("#,##0.#").format(this/Math.pow(1024.0, digitGroups.toDouble())) + " " + units[digitGroups];
}

fun Int.humanReadable(): String {
    return this.toLong().humanReadable()
}

次に簡単に使用されます:

println(1999549L.humanReadable())
println(someInt.humanReadable())

サンプルJava 7+パスクラスの拡張

拡張メソッドの一般的な使用例は、既存のAPIを改善することです。 Java 7+ PathクラスにexistnotExists 、およびdeleteRecursivelyを追加exist例を次に示します。

fun Path.exists(): Boolean = Files.exists(this)
fun Path.notExists(): Boolean = !this.exists()
fun Path.deleteRecursively(): Boolean = this.toFile().deleteRecursively()

この例でこれを呼び出すことができます:

val dir = Paths.get(dirName)
if (dir.exists()) dir.deleteRecursively()

拡張機能を使用して読みやすくする

Kotlinでは次のようなコードを書くことができます:

val x: Path = Paths.get("dirName").apply { 
    if (Files.notExists(this)) throw IllegalStateException("The important file does not exist")
}

しかし、 applyの使用は、あなたの意図と同じくらい明確ではありません。アクションの名前を変更してより自明なものにするために、同様の拡張機能を作成することが時々明確になります。これは手の届かないようにすべきではありませんが、確認のような非常に一般的な処置のために:

infix inline fun <T> T.verifiedBy(verifyWith: (T) -> Unit): T {
    verifyWith(this)
    return this
}

infix inline fun <T: Any> T.verifiedWith(verifyWith: T.() -> Unit): T {
    this.verifyWith()
    return this
}

コードを次のように書くことができます:

val x: Path = Paths.get("dirName") verifiedWith {
    if (Files.notExists(this)) throw IllegalStateException("The important file does not exist")
}

これは、ラムダパラメータ内で何を期待するかを人々に知らせます。

verifiedBy型パラメータTと同じであることに注意してくださいT: Any? null可能な型でもそのバージョンの拡張機能を使用できることを意味します。ただし、 verifiedWithはnullを指定できません。

ISO 8形式の文字列をレンダリングするためのJava 8 Temporalクラスの拡張サンプル

この宣言で:

fun Temporal.toIsoString(): String = DateTimeFormatter.ISO_INSTANT.format(this)

これで簡単に次のことができます:

val dateAsString = someInstant.toIsoString()

コンパニオンオブジェクトへの拡張関数(静的関数の出現)

クラスを拡張する場合は、静的関数の場合(たとえば、 Somethingクラスのstatic looking関数fromString追加するなど)は、クラスにコンパニオンオブジェクトがあり、その拡張関数がコンパニオンオブジェクトで宣言されている場合にのみ機能します:

class Something {
    companion object {}
}

class SomethingElse {
}

fun Something.Companion.fromString(s: String): Something = ... 

fun SomethingElse.fromString(s: String): SomethingElse = ... 

fun main(args: Array<String>) {
    Something.fromString("") //valid as extension function declared upon the
                             //companion object

    SomethingElse().fromString("") //valid, function invoked on instance not
                                   //statically

    SomethingElse.fromString("") //invalid
}

遅延拡張プロパティの回避策

あなたが計算するのに高価な拡張プロパティを作成したいとします。したがって、KotlinのKT-9686KT- 13053で説明されているように、 レイジープロパティデリゲートを使って計算をキャッシュし、現在のインスタンス( this )を参照することはできません。ただし、ここには公式の回避策があります

この例では、拡張プロパティはcolorです。これは明示的なcolorCacheを使用しています。 thislazyが必要でないため、 thisと共に使用できます:

class KColor(val value: Int)

private val colorCache = mutableMapOf<KColor, Color>()

val KColor.color: Color
    get() = colorCache.getOrPut(this) { Color(value, true) }

簡単な参照のための拡張コードからの表示

ビューを作成した後は、参照ビューの拡張機能を使用することができます。

Anko図書館によるオリジナルのアイデア

拡張機能

inline fun <reified T : View> View.find(id: Int): T = findViewById(id) as T
inline fun <reified T : View> Activity.find(id: Int): T = findViewById(id) as T
inline fun <reified T : View> Fragment.find(id: Int): T = view?.findViewById(id) as T
inline fun <reified T : View> RecyclerView.ViewHolder.find(id: Int): T = itemView?.findViewById(id) as T

inline fun <reified T : View> View.findOptional(id: Int): T? = findViewById(id) as? T
inline fun <reified T : View> Activity.findOptional(id: Int): T? = findViewById(id) as? T
inline fun <reified T : View> Fragment.findOptional(id: Int): T? = view?.findViewById(id) as? T
inline fun <reified T : View> RecyclerView.ViewHolder.findOptional(id: Int): T? = itemView?.findViewById(id) as? T

使用法

val yourButton by lazy { find<Button>(R.id.yourButtonId) }
val yourText by lazy { find<TextView>(R.id.yourTextId) }
val yourEdittextOptional by lazy { findOptional<EditText>(R.id.yourOptionEdittextId) }


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow