要点
- ComponentActivity が多数の interface を implements しているのを見て「こう書いて良い」と結論づけるのは誤読である。
- ComponentActivity の interface は全て Activity の本質的な責務 であり、is-a が成立している。
- フレームワークがそれらを引き受けているのは、アプリケーション側が余計な interface を背負わなくて済むようにするため である。
ComponentActivity のコード
|
|
Android のフレームワークコードには、多数の interface を implements しているクラスが存在する。これを見て「こういう書き方は OK なのだ」と結論づけるのは誤読である。このコードから読み取るべきことは、むしろ逆である。
doc comment が設計意図を語っている
Rather than all functionality being built directly into this class, only the minimal set of lower level building blocks are included. Higher level components can then be used as needed without enforcing a deep Activity class hierarchy or strong coupling between components.
(すべての機能をこのクラスに直接組み込むのではなく、最小限の低レベルな構成要素のみを含める。高レベルのコンポーネントは、深い Activity クラス階層やコンポーネント間の強い結合を強制することなく、必要に応じて使用できる)
Google 自身が「深い Activity クラス階層やコンポーネント間の強い結合を避けたい」と明言している。このクラスの設計意図自体が、「Activity に何でも載せるな」という主張を裏付けている。
is-a が成立する interface と成立しない interface
ComponentActivity の interface は全て is-a が成立している。
|
|
これらは全て Activity の本質的な責務 である。Activity がライフサイクルを持ち、ViewModel を管理し、状態を保存する — これは「代行」ではなく「本質」である。
一方で、アプリケーションコードにおける以下の記述はどうか。
|
|
クリック処理やテキスト監視は Activity の本質ではなく、たまたま代行しているだけ である。Activity の責務外であり、分離すべきである。
フレームワークコードとアプリケーションコードは立場が違う
| 観点 | ComponentActivity(フレームワーク) | MainActivity(アプリケーション) |
|---|---|---|
| 目的 | アプリコードがこれらを implements しなくて済むように、基盤として引き受ける | ビジネスロジックと UI を組み立てる |
| 設計判断 | 多くのレビューを経た意図的な設計 | 個々の開発者の判断 |
| 変更頻度 | 安定(API 互換性を保つ) | 頻繁(仕様変更のたびに変わる) |
ComponentActivity が LifecycleOwner 等を引き受けているのは、アプリケーション側の Activity がそれらを implements しなくて済むようにするため である。
つまり、このコードから読み取るべきメッセージは、
「フレームワークがここで引き受けたから、アプリコードでは余計な interface を背負うな」
ということである。
まとめ
- ComponentActivity の interface は全て Activity の本質的な責務であり、is-a が成立している。
- アプリケーションコードで
OnClickListener等を implements するのは、Activity の責務外の振る舞いを is-a で取り込む行為である。 - フレームワークのコードは「こう書いて良い」の根拠ではなく、「何をアプリコードから分離したかったか」を読み取る対象である。