1 00:00:00,440 --> 00:00:01,480 皆さん、こんにちは。 2 00:00:01,640 --> 00:00:03,400 第 3 講目へようこそ。 3 00:00:03,560 --> 00:00:06,040 今までに、継承や self 4 00:00:07,400 --> 00:00:10,400 メッセージ探索を見てきました。 では super を見てみましょう。 5 00:00:10,840 --> 00:00:14,280 最初に、super がレシーバーとなるような 6 00:00:14,880 --> 00:00:17,840 メッセージ送信を見てみましょう。 7 00:00:18,360 --> 00:00:19,840 super とは何でしょう? 8 00:00:20,120 --> 00:00:25,360 ちょっと時間をかけて 次の2点について定義を考えてみましょう。 9 00:00:26,040 --> 00:00:28,200 super は何を表わすのでしょうか? 10 00:00:30,400 --> 00:00:32,200 super へメッセージが送られた時 11 00:00:32,360 --> 00:00:34,240 メソッドはどのように探索されるでしょうか? 12 00:00:35,160 --> 00:00:36,560 次の原則は 13 00:00:36,920 --> 00:00:39,200 Pharo でも Java でも同じです。 14 00:00:39,560 --> 00:00:41,640 ここで見ている例は 15 00:00:42,800 --> 00:00:46,240 前の講義で見たものに似ています。 16 00:00:46,680 --> 00:00:49,360 super が1つのメソッドで使われています。 17 00:00:52,320 --> 00:00:55,600 何が起こるか、考えてみましょう。 18 00:00:56,440 --> 00:00:57,920 A new bar については 19 00:00:59,560 --> 00:01:00,920 問題ありません。 20 00:01:01,080 --> 00:01:03,120 前と同じプロセスです。 21 00:01:03,320 --> 00:01:05,600 メソッドが実行されて 22 00:01:06,160 --> 00:01:08,080 foo は 10 を返します。 23 00:01:10,320 --> 00:01:13,440 B new bar の場合について ステップ毎に見ていきましょう。 24 00:01:15,560 --> 00:01:17,960 メッセージ bar を 25 00:01:18,360 --> 00:01:20,720 オブジェクト B new に送ります。 26 00:01:22,080 --> 00:01:24,840 探索アルゴリズムはメソッド bar を 27 00:01:25,160 --> 00:01:27,160 そのオブジェクトのクラスから 探していきます。 28 00:01:27,320 --> 00:01:29,800 メソッド bar が見つかります。 29 00:01:30,880 --> 00:01:33,320 そのメソッドがレシーバの上で実行されます。 30 00:01:34,000 --> 00:01:38,680 この bar メソッドが メソッドの上で実行されます。 31 00:01:40,040 --> 00:01:43,440 ここで、「super bar」を 計算しなければなりません。 32 00:01:44,200 --> 00:01:46,640 そして「self foo」も実行して 両者を足し合わせます。 33 00:01:46,880 --> 00:01:48,600 「self foo」はできますね。 34 00:01:48,760 --> 00:01:53,400 「self foo」はオブジェクト self に メッセージ foo を送ります。 35 00:01:53,800 --> 00:01:55,600 self は B new です。 36 00:01:56,640 --> 00:02:00,080 可能なのは、クラス A の foo メソッドだけです。 37 00:02:01,280 --> 00:02:03,160 したがって、 self foo は 10 を返します。 38 00:02:04,840 --> 00:02:06,920 「super bar」では 39 00:02:08,000 --> 00:02:09,720 super がレシーバーです。 40 00:02:10,440 --> 00:02:12,920 探索アルゴリズムは 41 00:02:13,120 --> 00:02:15,720 レシーバー super があることで 変わってきます。 42 00:02:16,680 --> 00:02:19,840 探索アルゴリズムは キーワード super を含んでいるクラスの 43 00:02:20,320 --> 00:02:24,160 スーパークラスから メソッド bar を探し始めます。 44 00:02:25,080 --> 00:02:29,200 super は、クラス B の bar メソッドにあります。 45 00:02:29,640 --> 00:02:32,960 メソッド bar を探す開始点は 46 00:02:33,120 --> 00:02:35,680 B のスーパークラスである A になります。 47 00:02:36,240 --> 00:02:40,720 したがって、このメソッドが見つかります。 そして実行されます。 48 00:02:41,000 --> 00:02:43,200 foo が self に送られます。 49 00:02:43,360 --> 00:02:46,480 self は常にレシーバーオブジェクトです。 50 00:02:46,880 --> 00:02:47,880 つまり B new です。 51 00:02:48,120 --> 00:02:51,200 したがって foo は 最初のオブジェクトに送られます。 52 00:02:51,560 --> 00:02:54,640 これが実行された foo です。 10 が返されます。 53 00:02:56,800 --> 00:02:58,400 10 + 10 は 20 です。 54 00:03:00,320 --> 00:03:02,480 C new bar の場合には 55 00:03:02,920 --> 00:03:04,800 ここに C new とあります。 56 00:03:05,120 --> 00:03:09,120 それはクラス C のインスタンスです。 それにメッセージ bar を送ります。 57 00:03:09,800 --> 00:03:14,320 クラス C で bar を探します。 58 00:03:14,640 --> 00:03:17,080 見つかりません。 上位のクラスが探索されます。 59 00:03:17,480 --> 00:03:18,640 B で見つかります。 60 00:03:18,800 --> 00:03:22,400 それで B の bar が実行されます。 61 00:03:23,480 --> 00:03:27,960 この bar は 2 つのメッセージ送信の合計です。 62 00:03:28,640 --> 00:03:31,480 2つ目から始めてみます。 63 00:03:31,640 --> 00:03:34,640 メッセージ foo を オブジェクト self へ送ります。 64 00:03:34,880 --> 00:03:39,200 self はまだ C new です。 メッセージ foo を送ります。 65 00:03:40,120 --> 00:03:42,760 メソッドが見つかって、50 が返されます。 66 00:03:44,280 --> 00:03:45,880 ここに 50 を置いておきます。 67 00:03:46,440 --> 00:03:50,960 ここで、1つ目の部分である super bar が必要になります。 68 00:03:51,240 --> 00:03:55,200 メッセージ bar をsuper に送ります。 super は常にレシーバーです。 69 00:03:55,360 --> 00:03:58,280 しかし探索アルゴリズムが変わります。 70 00:03:59,000 --> 00:04:04,240 探索アルゴリズムはsuper を含むクラスの スーパークラスから bar を探します。 71 00:04:05,320 --> 00:04:08,720 それは B クラスの bar メソッドです。 72 00:04:09,000 --> 00:04:13,240 アルゴリズムは B のスーパークラスである A から bar を探し始めます。 73 00:04:13,880 --> 00:04:15,440 bar はここにあります。 74 00:04:15,880 --> 00:04:17,360 この bar が実行されます。 75 00:04:17,640 --> 00:04:20,920 self はまだ C new です。 まだこのままです。 76 00:04:21,080 --> 00:04:22,440 いつでもレシーバーです。 77 00:04:22,760 --> 00:04:24,440 メッセージ foo を送ります。 78 00:04:24,600 --> 00:04:27,960 結果は 50 です。ここに 50 が得られます。 79 00:04:28,280 --> 00:04:30,960 50 + 50 は 100 です。 80 00:04:31,680 --> 00:04:32,920 続くスライドで 81 00:04:33,360 --> 00:04:36,640 探索アルゴリズムのより詳細を見て 82 00:04:36,800 --> 00:04:38,680 深く学びましょう。 83 00:04:39,680 --> 00:04:42,880 super は常にレシーバーを指します。 84 00:04:43,040 --> 00:04:45,120 その点ではまさに self や 85 00:04:45,320 --> 00:04:47,200 Java の this と似ています。 86 00:04:47,480 --> 00:04:52,440 同様に、Java の super も this に似ています。 そして常にレシーバーを指します。 87 00:04:53,160 --> 00:04:57,520 しかし、super にメッセージが送られた時には 探索アルゴリズムが変わって 88 00:04:57,680 --> 00:05:01,360 実行されているメソッドを持つクラスの スーパークラスから 89 00:05:01,800 --> 00:05:05,680 メソッドを探し始めます。 90 00:05:06,040 --> 00:05:09,880 従って、self と super は根本的に異なります。 91 00:05:10,320 --> 00:05:13,640 self は動的ですが super は静的です。 92 00:05:13,880 --> 00:05:15,520 さらに説明をすると 93 00:05:17,080 --> 00:05:19,760 foo が self に送られた時には 94 00:05:20,360 --> 00:05:24,240 開発者は どの foo メソッドが実行されるか 全くわかりません。 95 00:05:24,880 --> 00:05:28,480 同じクラスの foo かもしれませんし 96 00:05:29,120 --> 00:05:31,840 今あるサブクラスの foo かもしれませんし 97 00:05:32,200 --> 00:05:35,640 他の開発者がそのプログラムを実行する 98 00:05:35,920 --> 00:05:38,040 直前に作った foo かもしれません。 99 00:05:38,720 --> 00:05:42,240 bar メソッドの開発者が self foo と書く時には 100 00:05:42,480 --> 00:05:45,640 その開発者には どの foo が実行されるか わからないのです。 101 00:05:46,080 --> 00:05:48,160 これは便利な機能です。 102 00:05:48,480 --> 00:05:51,280 つまり、開発者は新しいサブクラスを作って 103 00:05:51,440 --> 00:05:54,320 クラス A の振る舞いを 変えることができるのです。 104 00:05:55,440 --> 00:05:58,120 対照的に、super は静的です。 105 00:05:58,880 --> 00:06:03,400 開発者が super foo と書く時には 106 00:06:04,000 --> 00:06:06,920 プログラムを動かしたら どの foo メソッドが実行されるであろうか 107 00:06:07,080 --> 00:06:09,560 わかります。 108 00:06:09,840 --> 00:06:13,440 super foo とここに書く時には 109 00:06:14,280 --> 00:06:16,360 スーパークラス A の foo を指すのです。 110 00:06:16,880 --> 00:06:18,680 これが変わることはありません。 super は静的なのです。 111 00:06:18,880 --> 00:06:21,640 プログラムがどうコンパイルされるか わかります。 112 00:06:22,080 --> 00:06:25,360 残念なことに、書籍の中には 113 00:06:25,720 --> 00:06:28,160 super に間違った定義を しているものがあります。 114 00:06:28,320 --> 00:06:30,560 ナンセンスな定義です。 115 00:06:30,920 --> 00:06:33,800 ある本にあった定義はこうです。 116 00:06:34,320 --> 00:06:37,480 その本では、super は 117 00:06:37,920 --> 00:06:42,280 探索アルゴリズムに 118 00:06:42,440 --> 00:06:47,240 レシーバーのクラスのスーパークラスから メソッドを探すように指示する。 119 00:06:48,000 --> 00:06:50,480 レシーバーのクラスのスーパークラス、と。 120 00:06:50,640 --> 00:06:54,360 実際には、これは間違いです。 さきほど示した例で明らかなように。 121 00:06:54,800 --> 00:06:58,920 aC をレシーバーとした場合には そのクラスは C です。 122 00:06:59,720 --> 00:07:03,120 したがって、レシーバーのスーパークラスとは B のことになります。 123 00:07:04,040 --> 00:07:08,560 ここにきて super foo を実行する時には 124 00:07:08,960 --> 00:07:12,960 もしその本に書いてあった定義の通りだとすると 125 00:07:13,640 --> 00:07:16,360 メッセージ foo を 126 00:07:17,640 --> 00:07:20,520 super に送って実行されるのは 127 00:07:20,680 --> 00:07:24,320 レシーバーのクラスのスーパークラスの foo メソッドだということになります。 128 00:07:24,480 --> 00:07:27,480 つまり、これです。 129 00:07:27,840 --> 00:07:30,520 foo を super に 130 00:07:30,800 --> 00:07:34,480 何度も何度も送って 無限ループになります。 131 00:07:35,680 --> 00:07:38,280 つまりその定義は間違いです。 132 00:07:38,440 --> 00:07:43,760 実際には、この例は完璧に動きます。 133 00:07:44,240 --> 00:07:46,640 単純に、この定義が間違っているのです。 134 00:07:47,280 --> 00:07:49,480 覚えておくべきことは 135 00:07:50,040 --> 00:07:52,440 self は常にレシーバーを表わします。 136 00:07:52,680 --> 00:07:53,840 super も同様です。 137 00:07:54,000 --> 00:07:58,040 Java での this と super と同じです。 138 00:07:58,880 --> 00:08:01,160 しかし、super はメソッド探索を変えます。 139 00:08:01,600 --> 00:08:05,000 マッチを探し始めるのが 140 00:08:05,240 --> 00:08:07,320 キーワード super を含んでいる メソッドのクラスの 141 00:08:07,560 --> 00:08:12,160 スーパークラスになります。 142 00:08:12,720 --> 00:08:15,240 self は動的です。 143 00:08:15,640 --> 00:08:20,240 開発者は self を使って 既存のクラスの振る舞いを拡張することができます。 144 00:08:20,440 --> 00:08:23,440 メソッドを再定義するサブクラスを作ることで。