28
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Kotlinでスコープ関数「apply」を使えば、一時変数を書かなくてすむの巻

Posted at

こんにちは。

:hatched_chick:Kotlinを学びだすと、「なんだコレは?コレを使って何がオイシいのか?」と、その存在意義を疑いたくなるような感覚に陥っている最中の私です。:baby_chick:

特に、スコープ関数の「apply」がよく分からなくて腹が立ち減ります。
あゝ君は誰が為にスコープ関数を使ふのか。

自分で作ったクラスで有難味を知る

Item.kt
class Item(id: String, name: String, price: Int) {
    val id: String = id
    var name = name
    var price = price // 単価(税抜価格)
    var taxRate = 0.00
    var salePrice: Int = (price * taxRate).toInt() // 売価(税込価格)

    // 消費税率を設定
    fun setUpTaxRate(rate: Double) {
        taxRate = rate
    }
}

商品を表すクラスです。

  • 1989年4月:消費税法を施行。税率は3%。:money_with_wings::money_with_wings::money_with_wings:
  • 1997年4月:税率を5%に引き上げ。:money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings:
  • 2014年4月:税率を8%に引き上げ。:money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings:
  • 2019年10月?:税率を10%に引き上げ予定。:money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings::money_with_wings:

選挙に行きましょう。:inbox_tray:

SalesMan.kt
class SalesMan {

    fun sale1(): Item {
        var item = Item("A001", "自動扉冷蔵庫", 100000)
        item.setUpTaxRate(1.08)
        item.salePrice = (item.price * item.taxRate).toInt()
        return item
    }

    fun sale2(): Item {
        return Item("A001", "自動扉冷蔵庫", 100000).apply {
            setUpTaxRate(1.08)
            salePrice = (price * taxRate).toInt()
        }
    }
}
  • sale1()メソッドは、フツーに書いてみました。
  • sale2()メソッドこそ、スコープ関数「apply」を使って、6か所も書いた"item"を書かずに済みました
実行してみます
fun main(args: Array<String>) {
    val i1 = SalesMan().sale1()
    println("税込${i1.salePrice}円")
    val i2 = SalesMan().sale2()
    println("税込${i2.salePrice}円")
}

実行結果は同じです(税込108000円)。:yen:この記事を投稿した時点では、10万円の買い物で、8千円が消費税です...。:expressionless:

この「同じことを何度も書かずに済んだ」の恩恵は、次にBuilderパターンが適用されたクラスだと、より有難味があるかと思います。なぜなら、Kotlinの公式サイト上のイデオム例のひとつに、「Builder-style usage of methods that return Unit」というのが記載されています。

Java SE のAPIを使ってみて有難味を知る

java.utilパッケージに、JDK 1.8から導入され、Builderパターンが適用されたCalendar.Builderがあります。:flag_jp:平成31年4月30日は、西暦で何年で、何曜日でしょうか?

以下3パターンはすべてコンパイルが通ります。

これは愚なるコードよ
    val cb = Calendar.Builder() // Builderインスタンスを生成し、
    cb.setCalendarType("japanese") // 和暦に対応させて、
    cb.setDate(31, Calendar.APRIL, 30) // 第1引数は、現在の元号の年を渡し、
    cb.setTimeOfDay(5, 6, 4) // 時分秒も設定して、
    val calendar = cb.build()

せっかくのBuilderパターンを使わないという暴挙。cbを5か所も書いている。:angry:

書き改めます。

Builderパターンに従えども...
    val calendar = Calendar.Builder()
    .setCalendarType("japanese")
    .setDate(31, Calendar.APRIL, 30)
    .setTimeOfDay(5, 6, 4)
    .build()

メソッドチェーン:chains:するというのが、正しい用法かとは思うのですが、でもね、細かいこと言わせていただきますと、「.」記号がね、目障りなんですよ。セミコロンですら書くのが億劫だからKotlin使いたいんですよ、私は。:thinking:

これが一等素敵
import java.text.SimpleDateFormat
import java.util.Calendar

fun main(args: Array<String>) {
    val calendar = Calendar.Builder().apply {
        setCalendarType("japanese")
        setDate(31, Calendar.APRIL, 30)
        setTimeOfDay(5, 6, 4)
    }.build()

    val formatDate = SimpleDateFormat("GGGGyyyy年MM月dd日(E) ahh時mm分ss秒")
    print(formatDate.format(calendar.time))
}

実行結果は、西暦2019年で、火曜日でした。今回、時分秒はテキトーです(この時刻にとある儀式が催されるわけではありません)。

西暦2019年04月30日(火) 午前05時06分04秒

ともあれ、applyを使用したら、なんと「.」記号すら書かずに済むようになりました。

これがスコープ関数「apply」の活きる道、なのかと思われます。

以上です。

28
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?