VIDEO LESSON
TypeScriptのオブジェクト指向設計:カプセル化・インターフェース・委譲の解説動画
再生時間 7:47動画を別のタブで開く ↗
動画の字幕・文字起こしを読む
再生中の字幕を濃い黒で表示し、一番上に追従します。字幕の行を選ぶと、その位置から再生できます。
- 0:00こんにちは。
- 0:01今回のテーマは、タイプスクリプトのオブジェクト指向設計です。
- 0:06オブジェクト指向では、関連するデータと、そのデータを扱う処理をまとめ、役割のあるオブジェクト同士を組み合わせてプログラムを作ります。
- 0:17柱になるのは三つです。
- 0:19状態の変え方を限定するカプセル化、共通の約束を決めるインターフェース、そして仕事を別のオブジェクトへ任せる委譲です。
- 0:29クラスを増やせば自動的に保守性が上がるわけではありません。
- 0:34変更の影響範囲が分かること、状態の更新方法が明確なこと、必要な処理を差し替えやすいことを目標に、
- 0:39記事の二つの例で確認していきましょう。
- 0:45まず基本です。
- 0:46オブジェクトは、プロパティやメソッドを持つ値です。
- 0:51クラスは、そのようなオブジェクトを作成する方法の一つにすぎません。
- 0:56オブジェクトリテラルでも作れるため、すべてのオブジェクトにクラスが必要なわけではありません。
- 1:04では、どんなときにクラスが役立つのでしょうか。
- 1:08例えば記事の公開状態を管理するなら、状態と、状態を変更する処理を一緒に置くと、
- 1:13変更箇所を追いやすくなります。
- 1:18逆に、状態を持たない短い変換処理なら、関数だけで十分な場合もあります。
- 1:24道具ありきではなく、まとめたい状態と操作があるかどうかで判断するのが出発点です。
- 1:31カプセル化の実例が、アーティクルステータスクラスです。
- 1:35公開したかどうかを表すフラグは、シャープ付きのフィールドにして外から直接触れないようにします。
- 1:41タイトルはコンストラクタ引数のリードオンリーで受け取り、空のタイトルならエラーを投げて、
- 1:46そもそも作れないようにします。
- 1:50状態を変える入口はパブリッシュメソッドだけです。
- 1:53表示用のラベルはゲットラベルメソッドが組み立てます。
- 1:57実行すると、最初はタイプスクリプトの設計コロン下書き、パブリッシュした後は、
- 2:03タイプスクリプトの設計コロン公開中と表示され、記事の期待どおりでした。
- 2:08状態の操作方法を限定すること、これがカプセル化の具体例です。
- 2:12ここで仕組みの違いを整理します。
- 2:15シャープ付きフィールドはジャバスクリプトのプライベートフィールドで、実行時にもクラス外から直接アクセスできません。
- 2:25外から読もうとすると、コンパイルの段階でエラーになることも実機で確認しました。
- 2:32一方、タイプスクリプトのプライベートやリードオンリーは、型チェック上の制約で、
- 2:37シャープ付きとは仕組みが異なります。
- 2:42タイトルが空でないかの確認は、型とは別に実行時に行う検証です。
- 2:47空白だけのタイトルで作ろうとすると例外になることも確認済みです。
- 2:52なお、この例が扱うのはメモリ上の状態だけです。
- 2:56データベースへの保存や、本番サイトへの公開処理は含まれません。
- 3:02次にインターフェースです。
- 3:04メッセージライターというインターフェースは、文字列を受け取るライトメソッド一つを契約として決めます。
- 3:11これを実装するのが二つのクラスです。
- 3:14コンソールライターは受け取った文字列をそのまま画面へ出し、メモリライターは内部の配列へためておきます。
- 3:21クラスにインプリメンツと書くと、その契約を満たしているかが型チェックされます。
- 3:27ライトメソッドを書き忘れたクラスはエラーになることも実機で確認しました。
- 3:32同じ契約で異なる実装を扱えることが、次の委譲と多態性の土台になります。
- 3:38インターフェース自体は実行時には残らない、型の契約である点も覚えておきましょう。
- 3:43アーティクルサービスは、通知の文面を作る役割に集中し、実際の出力は別のオブジェクトへ任せます。
- 3:51これが委譲です。
- 3:52コンストラクタでメッセージライター型の値を受け取り、アナウンスメソッドは、
- 3:56そのライトを呼ぶだけです。
- 3:59具体的な出力先を内部で固定していないため、コンソールライターを渡せば画面へ、
- 4:04メモリライターを渡せば記録へと切り替えられます。
- 4:09実行結果は、新着記事コロン型の使い方、と、配列に新着記事コロンクラスの使い方が入った形で、
- 4:13記事と一致しました。
- 4:17同じ契約で実装を差し替えて扱うことを、ポリモーフィズム、多態性と呼びます。
- 4:23継承を使わなくても実現できる点がポイントです。
- 4:26メモリライターの細部にもカプセル化の工夫があります。
- 4:30ゲットメッセージズは、内部の配列そのものではなく、中身を複製した新しい配列を返します。
- 4:36もし内部配列をそのまま渡すと、呼び出し側が要素を追加したり書き換えたりしただけで、
- 4:40内部の記録まで変わってしまいます。
- 4:45コピーを返せば、その心配がありません。
- 4:47さらに戻り値の型にリードオンリーを付けると、タイプスクリプトの型チェックでも変更操作が制限されます。
- 4:54隠すのはフィールドだけではありません。
- 4:57取り出すときの渡し方まで含めて、状態の守り方を設計するのがカプセル化です。
- 5:02継承と委譲は、どちらが優れているかではなく、目的で使い分けます。
- 5:08継承は、既存のクラスをエクステンズで拡張し、親クラスとして扱える子クラスを作る方法です。
- 5:15共通の実装をまとめられる一方、親クラスの変更が子クラスへ影響します。
- 5:20同じ種類のオブジェクトとして扱えて、共通の実装も必要なら継承を検討します。
- 5:26一方、ある機能だけを交換・再利用したいなら、インターフェースと委譲が向いています。
- 5:32今回の出力先の差し替えがその例です。
- 5:35そして、状態を持たない短い変換処理なら、クラスにせず関数だけで十分な場合もあります。
- 5:42再利用したいのが実装なのか、機能なのかを先に言葉にすると、判断がぶれません。
- 5:48実行方法です。
- 5:49記事の例は、ストリクト、ターゲット・イーエス2020、モジュール・ノードネクストを指定してコンパイルし、
- 5:54生成されたジャバスクリプトを実行します。
- 5:59ファイルは二つ、アーティクルステータスとメッセージサービスで、それぞれ分けて試します。
- 6:05今回の検証でも、両ファイルともこの設定でコンパイルでき、出力がすべて記事と一致しました。
- 6:11二つ目の例は、外部サービスへの送信やネットワーク接続を行いません。
- 6:16依存する処理を差し替える考え方を、自分のパソコンの中だけで安全に確認できます。
- 6:22エラー時はジャバスクリプトが出力されない設定なので、古い出力の実行と混同しない点にも注意してください。
- 6:29最後に、オブジェクトの責務の見直しです。
- 6:32一つのクラスが、入力の検証、通信、表示をすべて担当すると、変更の影響が広がります。
- 6:38何の理由で修正される処理なのかを考え、独立して差し替えたい部分を別の役割に分けましょう。
- 6:44もう一つの観点が、テストのしやすさです。
- 6:47外部サービスの呼び出しのような依存を、引数やコンストラクタから渡せる形にしておくと、
- 6:52テストでは小さな代替実装を使えます。
- 6:56今回のメモリライターがまさにその役割で、実際の通信をしなくても、呼び出し側の振る舞いを確かめられます。
- 7:03設計の良し悪しは、テストのしやすさにも表れるのです。
- 7:07まとめです。
- 7:08カプセル化では、状態を隠し、変更の入口をメソッドへ限定します。
- 7:13インターフェースで契約を決めれば、実装を差し替えて扱う多態性が得られます。
- 7:18そして委譲では、必要な機能を別のオブジェクトへ任せ、自分のクラスは本来の役割に集中させます。
- 7:25継承は共通の実装が必要なときに選び、短い処理は関数で済ませる判断も大切です。
- 7:31練習として、メッセージライターの三つ目の実装、例えば件数だけ数えるライターを作り、
- 7:36アーティクルサービスへ渡してみてください。
- 7:40呼び出し側を一行も変えずに差し替えられれば、設計の狙いが体感できます。
- 7:45お疲れさまでした。
この動画で学べること
TypeScriptのオブジェクト指向をインターフェースとクラスの例で学びます。カプセル化・抽象化・多態性・継承と委譲、型と実行時の違いを解説します。
解説記事・サンプルコードを読む:TypeScriptのオブジェクト指向設計:カプセル化・インターフェース・委譲 →