ScalaでPimpMyLibraryのパターン
1. 序章
このチュートリアルでは、ScalaのPimpMyLibraryパターンについて説明します。 これは非常にシンプルでありながら非常に強力な概念であり、Scalaプログラムに柔軟性の次元を追加します。
2. Pimp My Library Patternとは何ですか?
これは、暗黙の変換を使用してライブラリを補足する機能を参照するための単なる凝った表現です。 Scalaの暗黙的なデザインパターンの詳細については、暗黙のクラスと暗黙の変換の穏やかな紹介をご覧ください。 これら2つを提供された順序で読むことをお勧めします。
ソフトウェアデザインパターンのより広い文脈では、これはデコレータデザインパターンを実現するための単純化された方法です。 コアScalaライブラリとsbtを介してインストールされたサードパーティライブラリの両方を「ポンピング」できます。
私たちは通常、コードの表現力を高めるためにライブラリを「pimp」します。
3. 典型的なユースケース
Slackワークスペースで、新しいメンバーが自己紹介をしながら自分自身について具体的なことを話してほしいと想像してみてください。 私たちは、名、第一言語、および業界での長年の経験に関心があります。
したがって、紹介は厳密に次のようになります。私の名前はXです。私の主要なプログラミング言語はYです。業界でZ年の経験があります。
これで、このような文字列に一致するSlackボットができ、任意の分析のために紹介を正常に取得できます。 たぶんそれはこれらのメンバーに興味があるかもしれないチャンネルを推薦することができます。
ボットは、名前とプログラミング言語だけでなく、ジュニア(0〜3歳)、ミドルレベル(4〜6歳)、シニア(7歳以上)の誰であるかを知る必要があります。
紹介情報を保持するクラスを作成しましょう。
case class IntroText(text: String) {
val tokens = text.split(" ")
def name: String = tokens(3)
def level: String = tokens(12).toInt match {
case 0 | 1 | 2 | 3 => "Junior"
case 4 | 5 | 6 => "MidLevel"
case _ => "Senior"
}
def language: String = tokens(9)
}
これらをテストして、動作を確認できます。
"Bot" should "detect new member details" in {
val intro = IntroText(
"My name is Fauz my primary programming language is
Scala I have 7 years of industry experience"
)
assertResult(expected = "Senior")(actual = intro.level)
assertResult(expected = "Scala")(actual = intro.language)
assertResult(expected = "Fauz")(actual = intro.name)
}
4. ポン引き文字列クラス
前の例は良いですが、もっとうまくやることができます。 メソッドlevel、 language 、および name は、Stringクラスで直接呼び出す場合と同じように呼び出すことができます。 これを行うには、暗黙の変換を使用してStringクラスをピンピングまたはデコレーションします。
implicit def stringToIntroText(str: String): IntroText = IntroText(str)
上記の定義は、通常のScala String->IntroTextメソッドです。 String を受け取り、IntroTextタイプに変換します。 Scalaコンパイラーがそれ以上の入力なしでそれを見つけることができるように、それを暗黙的にマークしました。
これで、IntroTextを使用法に表示する必要がなくなりました。
"Pimped Bot" should "detect new member details" in {
val intro =
"My name is Bengi my primary programming language is Java I have 2 years of industry experience"
assertResult(expected = "Junior")(actual = intro.level)
assertResult(expected = "Java")(actual = intro.language)
assertResult(expected = "Bengi")(actual = intro.name)
}
いくつかのことが内部で起こっています。 Scalaコンパイラは、Stringインスタンスでlevelなどのメソッド呼び出しを検出しましたが、そのようなメソッドはStringクラスに存在しません。 したがって、指定されたメソッドを持つスコープ内のクラスを探し、IntroTextを見つけます。
次に、StringからIntroTextへの暗黙的な変換があるかどうかを確認し、変数 intro、をIntroTextのインスタンスにアップグレードします。 ]。
5. 結論
この記事では、Scalaで非常に一般的に使用されているPimp MyLibraryPatternについて説明しました。 これは、デコレータパターンを適用して、既存のScala機能を使用してコードをより表現力豊かにする1つの方法です。
いつものように、完全なソースコードはGitHubでから入手できます。