WEBVTT

1
00:00:00.000 --> 00:00:00.887
こんにちは。

2
00:00:00.887 --> 00:00:04.581
今回のテーマは、タイプスクリプトのクラス継承です。

3
00:00:04.581 --> 00:00:10.345
継承とは、既存のクラスを土台にして、機能を足した新しいクラスを作る仕組みです。

4
00:00:10.345 --> 00:00:14.630
書き方を決めるキーワードは、エクステンズ、スーパー、オーバーライド、プロテクテッド、

5
00:00:14.630 --> 00:00:18.916
そしてアブストラクトの五つです。

6
00:00:18.916 --> 00:00:25.419
共通の状態や振る舞いは親クラスから引き継げますが、便利さだけで使う仕組みではありません。

7
00:00:25.419 --> 00:00:30.886
子クラスは、親クラスとして扱われても困らない、という契約まで引き継ぎます。

8
00:00:30.886 --> 00:00:35.542
その点を意識しながら、基本の書き方、親の処理の呼び出し方、情報の渡し方、

9
00:00:35.542 --> 00:00:40.197
実装を任せる方法の順に、実行例で確認していきましょう。

10
00:00:40.197 --> 00:00:46.108
各ファイルは独立した例として試せるので、一つずつ動かしながら読み進めてください。

11
00:00:46.108 --> 00:00:47.481
まず基本形です。

12
00:00:47.481 --> 00:00:54.173
パーソンクラスは、読み取り専用の名前を持ち、自己紹介のメソッドを備えています。

13
00:00:54.173 --> 00:01:01.381
スチューデントクラスは、エクステンズ・パーソンと書くことで、このクラスを継承します。

14
00:01:01.381 --> 00:01:06.787
すると名前と自己紹介は書かなくてもそのまま使え、子クラスでは学籍番号と、

15
00:01:06.787 --> 00:01:12.192
学習中であることを返すスタディメソッドだけを足せます。

16
00:01:12.192 --> 00:01:17.769
葵と101でインスタンスを作って実行すると、私の名前は葵です、葵は学習中です、

17
00:01:17.769 --> 00:01:23.347
学籍番号101、と表示され、記事の期待どおりでした。

18
00:01:23.347 --> 00:01:29.696
親の共通部分を一度だけ書き、子では違いに集中できるのが、継承の出発点です。

19
00:01:29.696 --> 00:01:33.371
継承で最初につまずきやすいのが、スーパーです。

20
00:01:33.371 --> 00:01:38.405
子クラスでコンストラクタを定義する場合、その中でスーパーに引数を渡して、

21
00:01:38.405 --> 00:01:43.439
親クラスのコンストラクタを呼び出さなければなりません。

22
00:01:43.439 --> 00:01:49.990
先ほどの例では、スーパー・カッコ・名前、として、親が必要とする名前を渡しています。

23
00:01:49.990 --> 00:01:54.465
大切な決まりは、ディスを使う前にスーパーを呼ぶことです。

24
00:01:54.465 --> 00:01:59.818
順番を逆にして、スーパーより前にディスの名前を読もうとすると、エラー・ティーエス17009などが発生することを、

25
00:01:59.818 --> 00:02:05.171
実機でも確認しました。

26
00:02:05.171 --> 00:02:10.764
まず親を初期化してから、子の初期化に進む、という順序で覚えてください。

27
00:02:10.764 --> 00:02:12.388
次はオーバーライドです。

28
00:02:12.388 --> 00:02:17.395
親と同じ名前のメソッドを子クラスに定義すると、振る舞いを置き換えられます。

29
00:02:17.395 --> 00:02:24.025
エンプロイークラスでは、イントロデュースをオーバーライドし、親の自己紹介に担当を付け足しています。

30
00:02:24.025 --> 00:02:30.115
ここでスーパー・ドット・イントロデュースと呼ぶと、親クラスの実装をそのまま再利用できます。

31
00:02:30.115 --> 00:02:36.610
注目点は、変数の型をパーソンと宣言しても、中身がエンプロイーなら子のメソッドが呼ばれることです。

32
00:02:36.610 --> 00:02:41.888
実行すると、私の名前は葵です、担当は開発です、と表示され、記事と一致しました。

33
00:02:41.888 --> 00:02:46.624
受け取る側は親の型だけを知っていればよい、という使い方につながります。

34
00:02:46.624 --> 00:02:52.686
オーバーライドの前にあるオーバーライドという修飾子には、役割があります。

35
00:02:52.686 --> 00:02:58.579
親クラスに同じメンバーが本当にあるかを、コンパイラに確認させる印です。

36
00:02:58.579 --> 00:03:04.472
さらにノーインプリシットオーバーライドを有効にすると、置き換えているのに印を付け忘れた場合に、

37
00:03:04.472 --> 00:03:10.365
エラー・ティーエス4114で知らせてくれます。

38
00:03:10.365 --> 00:03:15.417
この設定はストリクトとは別に指定する点にも注意してください。

39
00:03:15.417 --> 00:03:20.889
また、親が引数なしで呼べるメソッドに、子で必須の引数を足すような変更は、

40
00:03:20.889 --> 00:03:26.361
親の契約に反するためエラー・ティーエス2416になります。

41
00:03:26.361 --> 00:03:31.076
なお、型で自動選択されるオーバーロードとは別の概念です。

42
00:03:31.076 --> 00:03:36.756
プロテクテッドは、子クラスにだけ必要な情報を渡したいときの修飾子です。

43
00:03:36.756 --> 00:03:43.572
例では、ラベル付きアイテムのコンストラクタで、プロテクテッドなラベルを受け取ります。

44
00:03:43.572 --> 00:03:52.335
子クラスのメニューアイテムは、そのラベルを使って、角括弧で囲んだ文字列を返すレンダーメソッドを備えています。

45
00:03:52.335 --> 00:03:57.041
記事一覧で実行すると、角括弧付きの記事一覧と表示されます。

46
00:03:57.041 --> 00:04:07.428
一方、外部のコードからメニュー・ドット・ラベルと直接読むことはできず、エラー・ティーエス2445になることを実機で確認しました。

47
00:04:07.428 --> 00:04:14.568
外には隠しつつ、継承先の処理には材料を渡せる、という中間の公開範囲がプロテクテッドです。

48
00:04:14.568 --> 00:04:17.370
プライベートとの違いも整理しておきます。

49
00:04:17.370 --> 00:04:22.694
プライベートなメンバーは、それを宣言したクラスの中でしか直接参照できません。

50
00:04:22.694 --> 00:04:27.598
子クラスからも読めないため、親の内部だけに閉じたい情報に向いています。

51
00:04:27.598 --> 00:04:31.521
プロテクテッドは、そこへ継承先まで範囲を広げたものです。

52
00:04:31.521 --> 00:04:35.865
どちらも、タイプスクリプトの型チェックによるアクセス制限です。

53
00:04:35.865 --> 00:04:40.068
実行時にも本当にプライベートな値が必要な場合は、シャープ付きフィールドという、

54
00:04:40.068 --> 00:04:44.272
ジャバスクリプト側の別の仕組みを使います。

55
00:04:44.272 --> 00:04:49.876
子に渡す必要があるか、親の中だけに閉じるか、という目的で修飾子を選んでください。

56
00:04:49.876 --> 00:04:57.538
アブストラクトクラスは、共通部分だけを先に実装し、具体的な処理を子クラスへ任せたいときの仕組みです。

57
00:04:57.538 --> 00:05:05.813
ノーティフィケーションクラスでは、宛先を受け取り、宛先とメッセージを組み合わせるプレビューは親が実装します。

58
00:05:05.813 --> 00:05:13.628
一方、メッセージ自体を作るクリエイトメッセージは、アブストラクトなメソッドとして宣言だけで済ませます。

59
00:05:13.628 --> 00:05:17.306
ウェルカムノーティフィケーションがそれを実装し、登録ありがとうございます、

60
00:05:17.306 --> 00:05:20.983
という文面を返します。

61
00:05:20.983 --> 00:05:26.807
実行すると、葵宛、登録ありがとうございます、と表示され、記事と一致しました。

62
00:05:26.807 --> 00:05:30.944
なお、この例は表示するだけで、実際の送信は行いません。

63
00:05:30.944 --> 00:05:34.264
アブストラクトには、二つの約束があります。

64
00:05:34.264 --> 00:05:39.954
一つ目は、抽象クラス自体を直接ニューしてインスタンス化できないことです。

65
00:05:39.954 --> 00:05:43.590
試すと、エラー・ティーエス2511になります。

66
00:05:43.590 --> 00:05:48.175
土台だけのクラスからは、実物を作らない、という決まりです。

67
00:05:48.175 --> 00:05:54.498
二つ目は、具体的な子クラスは、抽象メソッドを必ず実装しなければならないことです。

68
00:05:54.498 --> 00:05:58.292
実装を欠いたクラスを書くと、エラー・ティーエス2515で指摘されることを、

69
00:05:58.292 --> 00:06:02.085
実機でも確認しました。

70
00:06:02.085 --> 00:06:06.749
裏を返せば、必要な実装を書き忘れたまま使えるようにはならないため、共通の手順に差し込む処理を、

71
00:06:06.749 --> 00:06:11.412
型の側でそろえられます。

72
00:06:11.412 --> 00:06:13.238
最後に、設計の判断です。

73
00:06:13.238 --> 00:06:18.412
継承が向いているのは、子クラスを親クラスとして自然に扱える関係です。

74
00:06:18.412 --> 00:06:26.325
親を受け取る関数に子を渡しても、引数の条件、戻り値、失敗したときの状態が矛盾しないかを確認してください。

75
00:06:26.325 --> 00:06:32.412
子だけが特別な前提を要求すると、親のつもりで使う側が予期しない失敗を起こします。

76
00:06:32.412 --> 00:06:37.586
逆に、同じ計算を使いたいだけなら、継承階層を増やす必要はありません。

77
00:06:37.586 --> 00:06:43.978
処理を関数や別のオブジェクトに任せる委譲なら、役割ごとに変更とテストを分けられます。

78
00:06:43.978 --> 00:06:50.217
階層を深くする前に、変更の影響を追いやすい構成かどうかを立ち止まって考えましょう。

79
00:06:50.217 --> 00:06:56.152
迷ったときは、親として扱えるか、という一文でテストすると判断しやすくなります。

80
00:06:56.152 --> 00:06:56.924
まとめです。

81
00:06:56.924 --> 00:07:02.969
エクステンズで土台を引き継ぎ、スーパーで親を初期化し、オーバーライドで振る舞いを置き換えます。

82
00:07:02.969 --> 00:07:06.120
子にだけ渡す情報にはプロテクテッド、実装を任せる共通の土台にはアブストラクト、

83
00:07:06.120 --> 00:07:09.271
という使い分けです。

84
00:07:09.271 --> 00:07:14.223
実行は、記事のファイルを保存し、ストリクトとノーインプリシットオーバーライドなどを付けたコマンドでコンパイルして、

85
00:07:14.223 --> 00:07:19.175
生成されたジャバスクリプトを実行します。

86
00:07:19.175 --> 00:07:23.033
節ごとにファイルは分け、例同士を一つに結合しないでください。

87
00:07:23.033 --> 00:07:26.184
練習として、新しい子クラスを一つ足す場合と、委譲で書く場合を比べてみると、

88
00:07:26.184 --> 00:07:29.336
判断の感覚がつかめます。

89
00:07:29.336 --> 00:07:34.094
継承は強力ですが、契約ごと引き継ぐ仕組みだという意識を忘れないでください。

90
00:07:34.094 --> 00:07:35.252
お疲れさまでした。
