1 00:00:00,480 --> 00:00:05,200 こんにちは。今日はプログラムの 2 00:00:05,360 --> 00:00:07,720 とても微妙なところを 分析してみましょう。 3 00:00:07,880 --> 00:00:11,640 まず最初に、ダイスプログラムを 振り返ってみましょう。 4 00:00:11,800 --> 00:00:16,520 覚えていると思いますが この演習ではダイスを定義して 5 00:00:16,680 --> 00:00:20,840 色々な面の数をもつダイスの インスタンスを定義しました。 6 00:00:21,000 --> 00:00:24,920 ダイスハンドルというクラスを 定義しました。 7 00:00:25,360 --> 00:00:29,440 そして DiceHandle クラスに 8 00:00:29,600 --> 00:00:31,320 + メソッドを実装して ダイスハンドル同士を足し合わせて 9 00:00:31,480 --> 00:00:34,840 新しいダイスハンドルを 作れるようにしました。 10 00:00:35,000 --> 00:00:37,600 これがこのクラスのコードです。 11 00:00:37,760 --> 00:00:40,680 DiceHandle new があります。 12 00:00:40,840 --> 00:00:42,920 新しいダイスハンドルを 作って 13 00:00:43,080 --> 00:00:46,680 レシーバーのダイスと 14 00:00:46,840 --> 00:00:48,200 もう1方のダイスを加えて 15 00:00:48,360 --> 00:00:52,040 メソッドの最後でこのハンドルを 返します。いいですね? 16 00:00:53,280 --> 00:00:57,960 今回は、この + メソッドで 17 00:00:58,120 --> 00:01:02,200 DiceHandle new と書く場合と self class new と書く場合の 18 00:01:02,360 --> 00:01:04,840 違いを見ていきます。 そしてこれらのうち 19 00:01:05,000 --> 00:01:07,560 どちらが優れているか その理由がわかるでしょう。 20 00:01:08,160 --> 00:01:09,840 ここにそのプログラムがあります。 21 00:01:10,200 --> 00:01:15,440 もし DiceHandle のサブクラスとして MemoDiceHandle を作って 22 00:01:16,080 --> 00:01:20,720 DiceHandle クラスから継承した + メソッドで MemoDiceHandle 同士を 23 00:01:20,880 --> 00:01:24,280 足し合わせたい場合には 24 00:01:24,440 --> 00:01:28,600 結果は DiceHandle クラスの インスタンスになります。 25 00:01:28,760 --> 00:01:30,880 MemoDiceHandle クラスの インスタンスではありません。 26 00:01:31,040 --> 00:01:33,840 これは問題です。 足し合わせたら 27 00:01:34,000 --> 00:01:36,720 同じ種類のものを 返してほしいからです。 28 00:01:36,880 --> 00:01:38,400 どうしたら良いでしょう? 29 00:01:38,560 --> 00:01:40,080 1 つ目の解決策は 30 00:01:40,480 --> 00:01:42,960 DiceHandle クラスの 31 00:01:43,120 --> 00:01:46,080 + メソッドの実装を変えます。 32 00:01:46,560 --> 00:01:48,080 + メソッドです。いいですね? 33 00:01:48,240 --> 00:01:53,280 そしてこのメソッドを追加します。 self handleClass 34 00:01:53,440 --> 00:01:58,320 インスタンス変数ではなく 35 00:01:58,480 --> 00:02:02,160 handleClass というメソッドを 使います。 that I call handleClass. 36 00:02:02,320 --> 00:02:05,160 DiceHandle では DiceHandle クラスを返します。 37 00:02:05,320 --> 00:02:09,800 サブクラスのMemoDiceHandle クラスでは MemoDiceHandle クラスを返します。 38 00:02:10,160 --> 00:02:14,480 つまり、単純に handleClass メソッドを 再定義することで 39 00:02:14,640 --> 00:02:19,720 正しいクラスのインスタンスを 得ることができます。 40 00:02:21,120 --> 00:02:25,280 同じコードを MemoDicehandle で実行したら、 41 00:02:25,440 --> 00:02:30,520 MemoDiceHandle クラスの インスタンスが得られます。 42 00:02:30,680 --> 00:02:33,680 MemoDiceHandle クラスの handleClass メソッドを 43 00:02:33,840 --> 00:02:38,280 再定義したからです。 サブクラスのインスタンスが得られます。 44 00:02:38,440 --> 00:02:42,160 これで目的は達成できます。 45 00:02:42,760 --> 00:02:46,200 問題は 46 00:02:46,360 --> 00:02:51,680 DiceHandle のサブクラスを 定義するたびに 47 00:02:51,840 --> 00:02:54,240 handleClass メソッドを 再定義しなければならないことです。 48 00:02:54,400 --> 00:02:59,600 再定義しなければ、 + メソッドは 正しいクラスのインスタンスを返しません。 49 00:02:59,760 --> 00:03:03,720 めんどくさいですね。 常に再定義しなければなりません。 50 00:03:03,880 --> 00:03:05,080 もう少し良い方法があります。 51 00:03:05,600 --> 00:03:09,000 2 つ目の解決策は 52 00:03:09,160 --> 00:03:13,200 DiceHandle クラスの + メソッドで 53 00:03:13,360 --> 00:03:16,160 self class new. とします。 54 00:03:17,000 --> 00:03:20,680 レシーバーにクラスを尋ねて 55 00:03:20,840 --> 00:03:22,640 インスタンスを得ます。 56 00:03:22,800 --> 00:03:27,240 self class は常にレシーバーの クラスを答えるので 57 00:03:27,400 --> 00:03:29,360 もしレシーバーがサブクラスならば 58 00:03:29,520 --> 00:03:33,520 正しくサブクラスを答えます。 例えば、MemoDiceHandle クラスです。 59 00:03:33,680 --> 00:03:37,840 レシーバーと同じ種類の インスタンスが得られます。 60 00:03:38,520 --> 00:03:40,480 まとめると 61 00:03:40,640 --> 00:03:42,400 見ての通り 62 00:03:42,800 --> 00:03:47,040 ダイスハンドルに + メッセージを送ると 63 00:03:47,200 --> 00:03:52,080 クラス名を書いた場合には 64 00:03:52,240 --> 00:03:56,760 サブクラスのインスタンスを得る上で 邪魔になります。 65 00:03:56,920 --> 00:04:01,400 self class new とすることで レシーバーのインスタンスが得られます。 66 00:04:01,560 --> 00:04:03,280 サブクラスの場合も含めて。 67 00:04:03,440 --> 00:04:06,920 つまり、self class new とした方が ずっと良いです。 68 00:04:07,080 --> 00:04:09,480 レシーバーの種類に応じて 69 00:04:10,120 --> 00:04:14,720 そのクラスのインスタンスを 直接得ることができます。