1前書き

Kotlinは、拡張を定義した後で、継承メソッドやデコレータパターンの形式を使わずに

既存のクラスを新しい機能で拡張する

便利な拡張メソッドの概念を導入します。私たちは基本的にそれを使うことができます – それはオリジナルのAPIの一部だったので。

自分のニーズに固有のメソッドを追加して、元のコードの一部のように見せることができるので、コードを読みやすく保守しやすくするために非常に役立ちます。情報源。

たとえば、__Stringに対してXMLエスケープを実行する必要があるかもしれません。標準のJavaコードでは、これを実行できるメソッドを記述して呼び出す必要があります。

String escaped = escapeStringForXml(input);

Kotlinで書かれているのに対し、スニペットは次のように置き換えることができます。

val escaped = input.escapeForXml()

これが読みやすくなるだけでなく、IDEは

String

クラスの標準メソッドと同じように、このメソッドをオートコンプリートオプションとして提供できます。


2標準ライブラリ拡張方法

Kotlin標準ライブラリには、いくつかの拡張メソッドが用意されています。


2.1. コンテキスト調整拡張メソッド

  • いくつかの一般的な拡張が存在し、私たちのアプリケーションのすべての型に適用することができます** 。これらは、コードが適切なコンテキストで実行されるようにするため、および場合によっては変数がnullにならないようにするために使用できます。

ほとんどの場合、これを実現せずに拡張機能を利用していることがわかります。

最も人気のあるものの1つは、おそらく

let()

メソッドです。これはKotlinのどのタイプでも呼び出すことができます – 初期値で実行される関数をそれに渡しましょう:

val name = "Baeldung"
val uppercase = name
  .let { n -> n.toUpperCase() }

これは、

Optional

または

Stream

クラスの

map()

メソッドに似ています。この場合は、指定された

String

を大文字の表現に変換するアクションを表す関数を渡します。

  • 変数

    name

    は、呼び出しの受信者として知られています** これは、それが拡張メソッドが作用している変数だからです。

これはsafe-callオペレータと一緒にうまく機能します。

val name = maybeGetName()
val uppercase = name?.let { n -> n.toUpperCase() }

  • この場合、

    let()

    に渡されたブロックは、変数

    name

    がnullではない** 場合にのみ評価されます。つまり、ブロック内では、値

    n

    は必ずNULLでないことが保証されています。このリンクに関する詳細:/kotlin-null-safety[ここ]。

私たちの必要性によっては、

let()

に代わる他の方法がありますが、それらも役に立つでしょう。


  • run()

    拡張子は

    let()

    と同じように動作しますが、呼ばれるブロック内の

    this

    値としてレシーバが提供されます。

val name = "Baeldung"
val uppercase = name.run { toUpperCase() }


  • apply()



    run()

    と同じように機能しますが、提供されたブロックから値を返す代わりにレシーバを返します** 。

関連する呼び出しを連鎖させるために

apply()

を利用しましょう。

val languages = mutableListOf<String>()
languages.apply {
    add("Java")
    add("Kotlin")
    add("Groovy")
    add("Python")
}.apply {
    remove("Python")
}


this



it

を明示的に使用しなくても、コードがより簡潔かつ表現力豊かになることに注目してください。


  • The()

    拡張は

    let()

    と同じように機能しますが、

    apply()

    と同じ方法でレシーバを返します。

val languages = mutableListOf<String>()
languages.also { list ->
    list.add("Java")
    list.add("Kotlin")
    list.add("Groovy")
}


  • takeIf()

    拡張は、受信側に作用する述語とともに提供され、この述語が

    true

    を返す場合は受信側を返します。 __メソッド:

val language = getLanguageUsed()
val coolLanguage = language.takeIf { l -> l == "Kotlin" }


  • takeUnless()

    拡張子は

    takeIf()

    と同じですが、述語論理が逆になっています。

val language = getLanguageUsed()
val oldLanguage = language.takeUnless { l -> l == "Kotlin" }


2.2. コレクションの拡張方法

  • Kotlinは、標準のJavaコレクションに多数の拡張メソッドを追加しています。これにより、コードの扱いが簡単になります。

これらのメソッドは

__Collections.kt、


__Ranges.kt

、および

__Sequences.kt

内にあり、代わりに

Arrays.に適用する同等のメソッドについては


Arrays.kt

があります。 (Kotlinでは、

Arrays



Collections

と同じように扱うことができます)。

ここで説明するには、これらの拡張方法が多すぎるため、これらのファイルを参照して、使用可能なものを確認してください。

  • コレクションに加えて、Kotlinは

    String

    クラス

    にかなりの数の拡張メソッドを追加します



    __Strings.kt

    で定義されています。

これらは

Strings

をあたかもそれらが文字の集合であるかのように扱うことを可能にします


_.

_

これらの拡張メソッドはすべて連携して動作しているため、コレクションの種類にかかわらず、コードを大幅にクリーンで簡単に作成できます。


3拡張メソッドを書く

それでは、JavaまたはKotlinの標準ライブラリから、あるいは使用している依存ライブラリから、新しい機能でクラスを拡張する必要がある場合はどうなりますか。

  • 拡張メソッドは他のメソッド** と同じように書かれていますが、レシーバクラスは関数名の一部としてピリオドで区切って提供されています。

例えば:

fun String.escapeForXml() : String {
    ....
}

これは

String

クラスへの拡張として

escapeForXml

と呼ばれる新しい関数を定義するでしょう。

  • この関数の内部では、

    String

    クラス自体の内部にこれを記述した場合と同じように、

    this

    を使用して受信側にアクセスできます。

fun String.escapeForXml() : String {
  return this
    .replace("&", "&amp;")
    .replace("<", "&lt;")
    .replace(">", "&gt;")
}


3.1. 一般的な拡張メソッドを書く

一般的に複数の型に適用されることを意図した拡張メソッドを書きたいとしたらどうでしょうか。

Any

型を拡張することもできます。これは、Javaの

Object

クラスと同等です – しかし、もっと良い方法があります。

  • 拡張方法は、一般的な受信機にも具体的な受信機にも適用することができます。

fun <T> T.concatAsString(b: T) : String {
    return this.toString() + b.toString()
}

これは一般的な必要条件を満たすどんな型にも適用することができ、そしてこの関数の中ではこの値は型保証です。

たとえば、上記の例を使用します。

5.concatAsString(10)//compiles
"5".concatAsString("10")//compiles
5.concatAsString("10")//doesn't compile


3.2. 中置型拡張メソッドの書き方

中置メソッドは、ピリオドや括弧なしでメソッドを呼び出すことができるので、DSLスタイルのコードを書くのに役立ちます。

infix fun Number.toPowerOf(exponent: Number): Double {
    return Math.pow(this.toDouble(), exponent.toDouble())
}

これを他の中置メソッドと同じように呼ぶことができます。

3 toPowerOf 2//9
9 toPowerOf 0.5//3


3.3. 演算子拡張メソッドを書く

拡張として演算子メソッドを書くこともできます。

  • 演算子メソッドは、完全なメソッド名** ではなく、演算子の短縮形を利用できるようにするものです。

operator fun List<Int>.times(by: Int): List<Int> {
    return this.map { it **  by }
}

繰り返しますが、これは他の演算子メソッドと同じように機能します。

listOf(1, 2, 3) **  4//[4, 8, 12]----

===  **  4概要**

拡張メソッドは、システムにすでに存在する型を拡張するのに便利なツールです。これらは、必要な機能を持っていないか、単にコードの特定の領域を管理しやすくするためです。

ここでは、システムで使用する準備ができているいくつかの拡張方法を見ました。さらに、拡張方法のさまざまな可能性を調べました。この機能のいくつかの例はhttps://github.com/eugenp/tutorials/tree/master/core-kotlin[GitHubに載って]を見てください。