スコープ関数のrun()関数を使わずに、ピリオドでメソッドを連結させる

金田著「[はじめてのandroidプログラミング 第５版](https://www.sbcr.jp/product/4815607968/)」を使って、勉強しています。

　「第９章カウントダウンタイマーを作ろう」で使っているkotlinの文法のテクニックを解析してみます。
　スコープ関数のrun関数を関数式に直してみます。
　はじめはrun関数の意味が分からなかったので、まずはrun関数を使わず、インスタンスを作り、そのメソッド()を一行１行、操作する古いやり方に書き換えようとしました。しかしSoundPoolクラスの[コンストラクタ](https://developer.android.com/reference/android/media/SoundPool#public-constructors_1)が非推奨になっていたので、本書のとおりSoundPool.Builder()でインスタンスを作ることにしました。調べて行く過程でrun関数を使わずに、ピリオドでメソッドを連結できることが分かったので紹介します。

　以下、本書を持っている前提で説明します。本書を使って勉強中の方、一緒に勉強しましょう。

##0.前提
　p253まで写経が済んでいるとします。

##1.原型
　p253まで写経が済んでいる状態のコードを示します。説明に不要な部分は、著作権に配慮して省略しています。
　本書のやり方では、SoundPool.Builder()のrun()関数の中に、AudioAttributesのインスタンスを作り出すAudioAttributes.Builderが含まれています。

```MainActicity.kt
class MainActivity : AppCompatActivity() {
    // 省略
    override fun onResume() {
        super.onResume()
        soundPool =
                SoundPool.Builder().run {
                    val audioAttributes = AudioAttributes.Builder().run {
                        this.setUsage(AudioAttributes.USAGE_ALARM)
                        this.build()
                    }
                    this.setMaxStreams(1)
                    this.setAudioAttributes(audioAttributes)
                    this.build()
                }
        // 省略
    }
    // 省略
}

```

##2.AudioAttributes.Builderを、SoundPool.Builder()のrun関数の外に出す
　先ずは、SoundPool.Builder()のrun関数の中に含まれているAudioAttributes.Builderを、SoundPool.Builder()のrun関数の外に出します。なおrun関数の動作については、本書p127に書かれています。

```MainActicity.kt
class MainActivity : AppCompatActivity() {
    // 省略
    override fun onResume() {
        super.onResume()

        val audioAttributes = AudioAttributes.Builder().run {    // (2)（１）をここへ移動する。（追記）
            this.setUsage(AudioAttributes.USAGE_ALARM)    // this.は省略可
            this.build()
        }

        soundPool = SoundPool.Builder().run {
            // val audioAttributes = AudioAttributes.Builder().run {    // (1)この部分を外に出す（削除）
            //    this.setUsage(AudioAttributes.USAGE_ALARM)
            //    this.build()
            // }
            this.setMaxStreams(1)
            this.setAudioAttributes(audioAttributes)
            this.build()
        }
        // 省略
    }
}
```

　ここで、 AudioAttributesクラスやSoundPoolクラスのインスタンスを作るのに、コンストラクタを用いることが非推奨であるから、AudioAttributes()やSoundPool()といった風にコンストラクタを使えないので、このままAudioAttributes.Builder()、SoundPool.Builder()を使ってインスタンスを作ることとした。

##3.ピリオドで連結する方法に変換する
　上記のコードをピリオドでメソッドを連結した形式に書き換えます。ピリオドで連結する形式に変換するにあたり、[nyan のアプリ開発](https://akira-watson.com/android/soundpool.html)を参考にした。

```MainActivity.kt
// 省略
    override fun onResume() {
        super.onResume()

        // 変換方法＜参考＞ https://akira-watson.com/android/kotlin/soundpool-play.html＞
        val audioAttributes = AudioAttributes.Builder()    // run()関数とthisを外し、関数をピリオド(.)連結する。
            .setUsage(AudioAttributes.USAGE_ALARM)
            .build()
        // val audioAttributes = AudioAttributes.Builder().run {    
        //     this.setUsage(AudioAttributes.USAGE_ALARM)    
        //     this.build()
        // }

        // 変換方法＜参考＞ https://akira-watson.com/android/kotlin/soundpool-play.html＞
        soundPool = SoundPool.Builder()    // run()関数とthisを外し、関数をピリオド(.)連結する。
            .setMaxStreams(1)
            .setAudioAttributes(audioAttributes)
            .build()
        // soundPool = SoundPool.Builder().run {
        //     this.setMaxStreams(1)
        //     this.setAudioAttributes(audioAttributes)
        //     this.build()
        // }

        // 省略
    }

// 省略
```
　ピリオドで連結する形が使えるのは、AudioAttributes.BuilderクラスやSoundPool.Builderクラスのメソッドの戻り値が、AudioAttributes.Builder型やSoundPool.Builder型であるからである。例えばAudioAttributes.Builderクラスのメソッド[setUsage()](https://developer.android.com/reference/android/media/AudioAttributes.Builder#setUsage(int))は、戻り値の型がAudioAttributes.Builderである。[setUsage()](https://developer.android.com/reference/android/media/AudioAttributes.Builder#setUsage(int))のリファレンスを参照して頂きたい。

　さて、第２項のrun()関数を使うやり方と第３項のピリオドで連結するやり方とでは、どちらが見やすいでしょうか？私は、電車ごっこのような、順繰りとタスクが進むピリオドで連結する方が、分かりやすく見やすいと思います。run関数を使うか、関数式を使うかの選択は、趣味の問題でしょうか？疑問が残ります。

##4.ピリオド連結を分解し、メソッドを一行一行処理する（2021/01/21追記）
　当初やり方が分からなかったが、落ち着いて考えたら方法を思いついたので記述する。
　ピリオドで連結していたメソッドを分解し、一行一行に変数を設けるようにコードを書き換える。

```MainActivity.kt

        //   val audioAttributes = AudioAttributes.Builder()
        //       .setUsage(AudioAttributes.USAGE_ALARM)
        //       .build()
        val buildedAudioAttributes = AudioAttributes.Builder()
        val setUsagedAudioAttributes = buildedAudioAttributes.setUsage(AudioAttributes.USAGE_ALARM)
        val audioAttributes = setUsagedAudioAttributes.build()
        
        // soundPool = SoundPool.Builder()
        //    .setMaxStreams(1)
        //    .setAudioAttributes(audioAttributes)
        //    .build()
        val buildedSoundPool = SoundPool.Builder()
        val setMaxStreamsedSoundPool = buildedSoundPool.setMaxStreams(1)
        val setAudioAttributedBuildedSoundPool = setMaxStreamsedSoundPool.setAudioAttributes(audioAttributes)
        soundPool = setAudioAttributedBuildedSoundPool.build()

        // 省略
```

##5.蛇足
　見た目、汚らしいですがrun()関数の中で、メソッドを連結することも出来るみたいです。第２項、第３項と比較してください。

【例１】

```MainActivity.kt
        soundPool = SoundPool.Builder().run {
            setMaxStreams(1)
                .setAudioAttributes(audioAttributes)     // ここから先を関数式で連結
                .build()
        }
```

　
【例２】

```MainActivity.kt
       soundPool = SoundPool.Builder().run {
            setMaxStreams(1)
            setAudioAttributes(audioAttributes)
                .build()     // これだけを関数式で連結
        }

```