1. 概要(Overview)
Pull Up Field は、サブクラスに重複して存在するフィールドを
スーパークラスへ移動(引き上げ) して共通化するリファクタリングです。
目的:
- 重複フィールドを一箇所にまとめることで保守性を向上
- 共通の属性をスーパークラスで管理して設計を明確化
- クラス階層の一貫性を高める
2. 適用シーン(When to Use)
- サブクラス間で 同じ名前・意味のフィールド を持っている
- 共通処理(メソッド)がそれらのフィールドに依存している
- スーパークラスに「共通の属性」として置いた方が自然
よくある匂い:
- Duplicate Code(重複コード)
- Parallel Inheritance Hierarchies(並行継承階層)
3. 手順(Mechanics / Steps)
- サブクラスのフィールドを調査し、同じ意味のものを特定
- スーパークラスにフィールドを追加
- サブクラスから重複フィールドを削除
- コンストラクタやアクセサを修正して共通フィールドを利用するように変更
- テストを実行し、挙動が変わらないことを確認
4. Kotlin 例(Before → After)
Before:サブクラスごとに重複
open class Employee
class Engineer(val name: String) : Employee()
class Manager(val name: String) : Employee()
-
EngineerとManagerがどちらもnameを持っている → 重複
After:フィールドをスーパークラスに引き上げ
open class Employee(val name: String)
class Engineer(name: String) : Employee(name)
class Manager(name: String) : Employee(name)
-
nameをEmployeeに引き上げて共通化 - 各サブクラスはシンプルになり、共通メソッドでも
nameを扱える
発展例:共通処理でも活用可能
open class Employee(val name: String) {
fun printName() = println("Employee: $name")
}
class Engineer(name: String) : Employee(name)
class Manager(name: String) : Employee(name)
fun main() {
val eng = Engineer("Alice")
val mgr = Manager("Bob")
eng.printName() // Employee: Alice
mgr.printName() // Employee: Bob
}
5. 効果(Benefits)
- 重複排除 → メンテナンスが楽になる
- 共通の属性を 一元的に管理できる
- サブクラスがシンプル化し、階層構造が明確になる
- 共通メソッドでスーパークラスのフィールドを直接使える
6. 注意点(Pitfalls)
- 本当に「全サブクラス共通」かを慎重に判断する必要あり
- 一部のサブクラスにしか不要なら Push Down Field が適切
- 引き上げによってスーパークラスの責務が増えすぎると God Class 化 のリスク
- サブクラス固有の意味を「無理に共通化」すると設計が不自然になる
まとめ
- Pull Up Field は、サブクラス間の共通フィールドを スーパークラスに移動 して重複をなくすリファクタリング
- 判断基準:すべてのサブクラスに共通する属性か?
- 基本思想:共通点は上位に集約し、サブクラスは固有の責務に集中させる