﻿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
メソッドを再定義するサブクラスを作ることで。
