WEBVTT

00:00:00.480 --> 00:00:05.200 align:middle
こんにちは。今日はプログラムの

00:00:05.360 --> 00:00:07.720 align:middle
とても微妙なところを
分析してみましょう。

00:00:07.880 --> 00:00:11.640 align:middle
まず最初に、ダイスプログラムを
振り返ってみましょう。

00:00:11.800 --> 00:00:16.520 align:middle
覚えていると思いますが
この演習ではダイスを定義して

00:00:16.680 --> 00:00:20.840 align:middle
色々な面の数をもつダイスの
インスタンスを定義しました。

00:00:21.000 --> 00:00:24.920 align:middle
ダイスハンドルというクラスを
定義しました。

00:00:25.360 --> 00:00:29.440 align:middle
そして DiceHandle クラスに

00:00:29.600 --> 00:00:31.320 align:middle
+ メソッドを実装して
ダイスハンドル同士を足し合わせて

00:00:31.480 --> 00:00:34.840 align:middle
新しいダイスハンドルを
作れるようにしました。

00:00:35.000 --> 00:00:37.600 align:middle
これがこのクラスのコードです。

00:00:37.760 --> 00:00:40.680 align:middle
DiceHandle new があります。

00:00:40.840 --> 00:00:42.920 align:middle
新しいダイスハンドルを
作って

00:00:43.080 --> 00:00:46.680 align:middle
レシーバーのダイスと

00:00:46.840 --> 00:00:48.200 align:middle
もう1方のダイスを加えて

00:00:48.360 --> 00:00:52.040 align:middle
メソッドの最後でこのハンドルを
返します。いいですね？

00:00:53.280 --> 00:00:57.960 align:middle
今回は、この + メソッドで

00:00:58.120 --> 00:01:02.200 align:middle
DiceHandle new と書く場合と
self class new と書く場合の

00:01:02.360 --> 00:01:04.840 align:middle
違いを見ていきます。
そしてこれらのうち

00:01:05.000 --> 00:01:07.560 align:middle
どちらが優れているか
その理由がわかるでしょう。

00:01:08.160 --> 00:01:09.840 align:middle
ここにそのプログラムがあります。

00:01:10.200 --> 00:01:15.440 align:middle
もし DiceHandle のサブクラスとして
MemoDiceHandle を作って

00:01:16.080 --> 00:01:20.720 align:middle
DiceHandle クラスから継承した
+ メソッドで MemoDiceHandle 同士を

00:01:20.880 --> 00:01:24.280 align:middle
足し合わせたい場合には

00:01:24.440 --> 00:01:28.600 align:middle
結果は DiceHandle クラスの
インスタンスになります。

00:01:28.760 --> 00:01:30.880 align:middle
MemoDiceHandle クラスの
インスタンスではありません。

00:01:31.040 --> 00:01:33.840 align:middle
これは問題です。
足し合わせたら

00:01:34.000 --> 00:01:36.720 align:middle
同じ種類のものを
返してほしいからです。

00:01:36.880 --> 00:01:38.400 align:middle
どうしたら良いでしょう？

00:01:38.560 --> 00:01:40.080 align:middle
1 つ目の解決策は

00:01:40.480 --> 00:01:42.960 align:middle
DiceHandle クラスの

00:01:43.120 --> 00:01:46.080 align:middle
+ メソッドの実装を変えます。

00:01:46.560 --> 00:01:48.080 align:middle
+ メソッドです。いいですね？

00:01:48.240 --> 00:01:53.280 align:middle
そしてこのメソッドを追加します。
self handleClass

00:01:53.440 --> 00:01:58.320 align:middle
インスタンス変数ではなく

00:01:58.480 --> 00:02:02.160 align:middle
handleClass というメソッドを
使います。
that I call handleClass.

00:02:02.320 --> 00:02:05.160 align:middle
DiceHandle では
DiceHandle クラスを返します。

00:02:05.320 --> 00:02:09.800 align:middle
サブクラスのMemoDiceHandle クラスでは
MemoDiceHandle クラスを返します。

00:02:10.160 --> 00:02:14.480 align:middle
つまり、単純に handleClass メソッドを
再定義することで

00:02:14.640 --> 00:02:19.720 align:middle
正しいクラスのインスタンスを
得ることができます。

00:02:21.120 --> 00:02:25.280 align:middle
同じコードを
MemoDicehandle で実行したら、

00:02:25.440 --> 00:02:30.520 align:middle
MemoDiceHandle クラスの
インスタンスが得られます。

00:02:30.680 --> 00:02:33.680 align:middle
MemoDiceHandle クラスの
handleClass メソッドを

00:02:33.840 --> 00:02:38.280 align:middle
再定義したからです。
サブクラスのインスタンスが得られます。

00:02:38.440 --> 00:02:42.160 align:middle
これで目的は達成できます。

00:02:42.760 --> 00:02:46.200 align:middle
問題は

00:02:46.360 --> 00:02:51.680 align:middle
DiceHandle のサブクラスを
定義するたびに

00:02:51.840 --> 00:02:54.240 align:middle
handleClass メソッドを
再定義しなければならないことです。

00:02:54.400 --> 00:02:59.600 align:middle
再定義しなければ、 + メソッドは
正しいクラスのインスタンスを返しません。

00:02:59.760 --> 00:03:03.720 align:middle
めんどくさいですね。
常に再定義しなければなりません。

00:03:03.880 --> 00:03:05.080 align:middle
もう少し良い方法があります。

00:03:05.600 --> 00:03:09.000 align:middle
2 つ目の解決策は

00:03:09.160 --> 00:03:13.200 align:middle
DiceHandle クラスの + メソッドで

00:03:13.360 --> 00:03:16.160 align:middle
self class new.
とします。

00:03:17.000 --> 00:03:20.680 align:middle
レシーバーにクラスを尋ねて

00:03:20.840 --> 00:03:22.640 align:middle
インスタンスを得ます。

00:03:22.800 --> 00:03:27.240 align:middle
self class は常にレシーバーの
クラスを答えるので

00:03:27.400 --> 00:03:29.360 align:middle
もしレシーバーがサブクラスならば

00:03:29.520 --> 00:03:33.520 align:middle
正しくサブクラスを答えます。
例えば、MemoDiceHandle クラスです。

00:03:33.680 --> 00:03:37.840 align:middle
レシーバーと同じ種類の
インスタンスが得られます。

00:03:38.520 --> 00:03:40.480 align:middle
まとめると

00:03:40.640 --> 00:03:42.400 align:middle
見ての通り

00:03:42.800 --> 00:03:47.040 align:middle
ダイスハンドルに
+ メッセージを送ると

00:03:47.200 --> 00:03:52.080 align:middle
クラス名を書いた場合には

00:03:52.240 --> 00:03:56.760 align:middle
サブクラスのインスタンスを得る上で
邪魔になります。

00:03:56.920 --> 00:04:01.400 align:middle
self class new とすることで
レシーバーのインスタンスが得られます。

00:04:01.560 --> 00:04:03.280 align:middle
サブクラスの場合も含めて。

00:04:03.440 --> 00:04:06.920 align:middle
つまり、self class new とした方が
ずっと良いです。

00:04:07.080 --> 00:04:09.480 align:middle
レシーバーの種類に応じて

00:04:10.120 --> 00:04:14.720 align:middle
そのクラスのインスタンスを
直接得ることができます。

