1. 概要(Overview)
Introduce Local Extension は、既存のクラスに便利なメソッドを追加したいが、
- そのクラスを直接修正できない(外部ライブラリや標準 API)
- しかも 複数の関連メソッドをまとめて追加したい
といったケースで使うリファクタリングです。
Kotlin では 拡張関数や拡張プロパティをまとめたクラス/ファイル を導入する形になります。
Java ならユーティリティクラスを導入して、既存クラスに「追加 API」を提供するのが一般的です。
目的は以下の通りです:
- 外部クラスに対する操作を拡張しつつ、整理してまとめる
- 再利用性を高め、重複を減らす
- クライアントコードをシンプルで表現力豊かにする
2. 適用シーン(When to Use)
- 外部クラスに 複数の便利メソッドを追加したい
- それらを 1つのまとまり(拡張クラス/拡張ファイル) として管理したい
- プロジェクト内で ローカルにだけ必要な拡張 を導入したい
例:
-
LocalDateに「翌日」「月末」「週の始まり」などの操作を追加 -
Stringに「isEmail」「isPhoneNumber」「mask」などを追加
3. 手順(Mechanics / Steps)
- 外部クラスに追加したい便利メソッドを洗い出す
- 新しい拡張クラス(または拡張用ファイル)を作成
- 拡張関数や拡張プロパティを定義
- クライアントコードからそれを利用するように変更
- テストで正しく動作することを確認
4. Kotlin 例(Before → After)
Before:外部クラスを毎回直接操作している
import java.time.LocalDate
fun printDates(date: LocalDate) {
val tomorrow = date.plusDays(1)
val monthEnd = date.withDayOfMonth(date.lengthOfMonth())
println("Tomorrow: $tomorrow, End of Month: $monthEnd")
}
-
plusDaysやwithDayOfMonthが毎回登場して冗長 - 「明日」「月末」といった意味が伝わりにくい
After:ローカル拡張を導入
import java.time.LocalDate
// ✅ LocalDate 用の拡張をまとめる
object LocalDateExtensions {
fun LocalDate.nextDay(): LocalDate = this.plusDays(1)
fun LocalDate.endOfMonth(): LocalDate = this.withDayOfMonth(this.lengthOfMonth())
}
// クライアントコード
fun printDates(date: LocalDate) {
with(LocalDateExtensions) {
println("Tomorrow: ${date.nextDay()}, End of Month: ${date.endOfMonth()}")
}
}
→ LocalDate に本来あるかのように自然に使える。
→ 複数の便利メソッドをまとめて管理できる。
After②:Kotlin ならファイルレベルで拡張を定義してもOK
// LocalDateExt.kt
package extensions
import java.time.LocalDate
fun LocalDate.nextDay(): LocalDate = this.plusDays(1)
fun LocalDate.endOfMonth(): LocalDate = this.withDayOfMonth(this.lengthOfMonth())
クライアントコード:
import extensions.*
fun printDates(date: LocalDate) {
println("Tomorrow: ${date.nextDay()}, End of Month: ${date.endOfMonth()}")
}
5. 効果(Benefits)
- 外部クラスを「ローカルで拡張」でき、自然な API で利用可能
- 関連する拡張をまとめることで 整理しやすく再利用性が高い
- クライアントコードがシンプルで表現力豊かになる
6. 注意点(Pitfalls)
- 拡張が増えすぎると 本来のクラスの API と競合する危険がある
- プロジェクト全体で拡張をどう管理するかルールを決めないと、乱立してスパゲッティ化する
- 公開 API に含めるか、ローカル専用にとどめるか を明確にする
まとめ
- Introduce Local Extension は「外部クラスに複数の便利メソッドをまとめて追加」するリファクタリング
- 判断基準:この拡張はプロジェクト全体で必要か?ローカルで十分か?
- 基本思想:拡張を整理し、自然な API として使えるようにする