1 00:00:08,000 --> 00:00:12,320 やあ、みなさん、このビデオでは クラスの上級編をお見せします。 2 00:00:13,720 --> 00:00:15,320 3 つのことをします。 3 00:00:15,520 --> 00:00:20,760 1 つ目は、クラスやそのサブクラスの インスタンス間での状態の共有です。 4 00:00:22,280 --> 00:00:27,240 2 つ目は、クラス自身に変数を 持たせる方法です。 5 00:00:28,600 --> 00:00:30,960 3 つ目は、クラスの初期化です。 6 00:00:32,760 --> 00:00:36,160 まず最初に、インスタンス間で 状態を共有する方法です。 7 00:00:37,560 --> 00:00:41,640 ここにクラスと いくつかのインスタンスがあります。 8 00:00:41,920 --> 00:00:47,200 状態を共有するためには、これらの インスタンスに共通するオブジェクトが必要です。 9 00:00:47,720 --> 00:00:53,920 Java では、「静的(static)」な インスタンス変数を使います。 10 00:00:55,160 --> 00:00:58,240 静的な変数の値は 11 00:00:58,680 --> 00:01:00,720 全てのインスタンスで同じです。 12 00:01:01,640 --> 00:01:04,640 Pharo ではクラス変数を使います。 13 00:01:06,200 --> 00:01:11,120 これはクラスを作るときの 見慣れた表現式ですね。 14 00:01:11,480 --> 00:01:15,640 ここでは Color クラスを作っています。 Object のサブクラスです。 15 00:01:15,800 --> 00:01:21,600 まず、インスタンス変数を列挙していて その次の行を見ると 16 00:01:21,920 --> 00:01:25,480 Color クラスのクラス変数を 列挙しています。 17 00:01:26,640 --> 00:01:32,200 Color クラスには少なくとも2つの変数があります。 ColorRegistry と ComponentMask です。 18 00:01:32,720 --> 00:01:34,440 クラス変数の値は 19 00:01:34,680 --> 00:01:39,400 そのクラスとサブクラスの 全てのインスタンスに共有されます。 20 00:01:40,480 --> 00:01:46,600 これらの変数はインスタンスメソッドからも クラスメソッドからもアクセス可能です。 21 00:01:47,480 --> 00:01:49,920 クラス変数は大文字で始まります。 22 00:01:50,520 --> 00:01:52,840 例題に戻りましょう。 23 00:01:53,320 --> 00:01:55,600 Color クラスは 24 00:01:55,920 --> 00:01:59,520 メタクラス Color class の インスタンスです。 25 00:02:01,160 --> 00:02:06,760 Color クラスでは 2 つのインスタンス変数 が定義されています。grb と alpha です。 26 00:02:06,960 --> 00:02:09,720 これらのインスタンス変数はプライベートです。 27 00:02:10,760 --> 00:02:16,240 つまり、Color クラスのメソッドからしか アクセスできません。 28 00:02:18,440 --> 00:02:24,560 ColorRegistry も定義されています。 これは下線が引かれ大文字になっています。 29 00:02:25,240 --> 00:02:28,360 つまりこの変数は共有されている ということを示しています。 30 00:02:29,480 --> 00:02:33,080 この変数はクラス変数で 31 00:02:33,600 --> 00:02:39,640 Color クラスや Color class クラスの メソッドからアクセス可能です。 32 00:02:40,240 --> 00:02:43,600 この変数を使った例があります。 33 00:02:44,000 --> 00:02:48,520 Color クラスの privateBlue という インスタンスメソッドでは 34 00:02:48,840 --> 00:02:54,320 クラス変数を名前でアクセスしています。 35 00:02:55,360 --> 00:02:59,280 同様に、この変数に値を代入するには 36 00:02:59,640 --> 00:03:03,560 := を使います。他の変数と同じです。 37 00:03:03,880 --> 00:03:06,920 インスタンス側でもクラス側でも可能です。 38 00:03:07,400 --> 00:03:08,480 よくある使い方は 39 00:03:09,000 --> 00:03:14,720 クラス変数の値が 40 00:03:15,800 --> 00:03:17,600 インスタンスメソッドで読まれて 41 00:03:17,800 --> 00:03:21,680 クラスメソッドで書き込みます。 42 00:03:22,080 --> 00:03:25,960 よく使われるやり方ですが そうしなければならないというわけではありません。 43 00:03:28,040 --> 00:03:31,440 では、クラスのインスタンス変数を 見てみましょう。 44 00:03:33,320 --> 00:03:34,920 これはこれで別物です。 45 00:03:35,200 --> 00:03:38,360 クラスはオブジェクトです。 他のオブジェクトと同様に。 46 00:03:38,520 --> 00:03:41,600 他のオブジェクトと同様に クラスもインスタンス変数を持つことができます。 47 00:03:42,440 --> 00:03:48,560 メタクラスがクラスを定義して インスタンス変数を列挙します。 48 00:03:48,760 --> 00:03:52,800 それらのインスタンス変数はそのシングルトンである クラスからのみアクセスできます。 49 00:03:53,440 --> 00:03:57,840 クラス側にインスタンス変数を定義するには 50 00:03:58,480 --> 00:04:02,000 コードブラウザの 「class」ボタンをクリックします。 51 00:04:02,160 --> 00:04:04,400 するとこの表現式が出てきます。 52 00:04:04,560 --> 00:04:07,840 今、RPackageSet クラスを ブラウズしていますが 53 00:04:08,280 --> 00:04:13,400 このクラスのメタクラスは cachePackages という名前の変数を定義しています。 54 00:04:15,440 --> 00:04:19,240 こういった変数はクラスメソッドからのみ アクセスすることができます。 55 00:04:20,280 --> 00:04:24,920 そして必ず小文字で始まります。 56 00:04:25,800 --> 00:04:27,240 例題があります。 57 00:04:27,960 --> 00:04:32,960 変数 cachePackages は メタクラス RPackageSet class で 58 00:04:35,280 --> 00:04:36,720 定義されています。 つまり 59 00:04:37,520 --> 00:04:42,480 RPackageSet クラスはメタクラス RPackageSet class のインスタンスですが 60 00:04:42,640 --> 00:04:45,560 この変数に関連付けられた値を持っています。 61 00:04:46,840 --> 00:04:48,080 同様に 62 00:04:49,280 --> 00:04:53,760 RPackageSet クラスの全てのサブクラスは 63 00:04:54,000 --> 00:04:58,600 この変数の それぞれの異なる値を持っています。 64 00:04:58,760 --> 00:05:00,400 共有されていません。 65 00:05:00,600 --> 00:05:04,920 RPackageSet クラスやそのサブクラスは 66 00:05:05,080 --> 00:05:07,600 この変数にそれぞれの値を持っています。 67 00:05:08,040 --> 00:05:14,040 クラス変数とクラス側のインスタンス変数は 別のものです。 68 00:05:14,200 --> 00:05:17,960 シングルトンパターンを使って説明します。 69 00:05:18,160 --> 00:05:23,240 シングルトンパターンの目的はクラスのインスタンスが 1つだけであることを保証することです。 70 00:05:24,800 --> 00:05:29,720 このパターンを実装する方法の 1 つは 変数にインスタンスを格納して 71 00:05:30,920 --> 00:05:36,160 そのインスタンスへのアクセスを提供して インスタンス生成を無効化することです。 72 00:05:36,920 --> 00:05:39,920 WebServer でそれをやってみます。 73 00:05:41,040 --> 00:05:45,440 ここでクラス側の インスタンス変数を使います。 74 00:05:46,760 --> 00:05:48,960 名前は小文字になっています。 75 00:05:49,120 --> 00:05:53,200 この変数はメタクラスの定義で 宣言されています。 76 00:05:53,760 --> 00:05:56,920 そして new メソッドの実行を 無効化しています。 77 00:05:57,200 --> 00:06:02,040 WebServer クラスに新しいインスタンスを 作るようにメッセージを送ることはできません。 78 00:06:02,240 --> 00:06:05,200 uniqueInstance を経由するように 強制されています。 79 00:06:05,360 --> 00:06:10,640 変数の値が nil でなければ その値が返されて 80 00:06:11,200 --> 00:06:15,440 nil であれば super new を使って その変数にインスタンスを与えます。 81 00:06:15,600 --> 00:06:18,840 WebServer クラスの 新しいインスタンスを生成して 82 00:06:19,000 --> 00:06:21,960 変数 uniqueInstance に格納します。 83 00:06:22,560 --> 00:06:27,760 実際にクラスインスタンス変数を使うと 84 00:06:28,400 --> 00:06:30,480 次のような結果になります。 85 00:06:31,240 --> 00:06:34,000 WebServer クラスの各サブクラス毎に 86 00:06:34,520 --> 00:06:36,640 それぞれ異なるインスタンスが 87 00:06:37,240 --> 00:06:39,640 uniqueInstance に格納されます。 88 00:06:40,120 --> 00:06:43,040 つまり、WebServer クラスに サブクラスが 3 つあれば 89 00:06:43,200 --> 00:06:47,480 変数 uniqueInstance には 合計 4 つの値があることになります。 90 00:06:47,640 --> 00:06:50,600 WebServer クラスに 1 つと 各サブクラスに 1 つずつです。 91 00:06:51,320 --> 00:06:54,600 クラス変数を使うと 92 00:06:55,160 --> 00:07:00,000 このクラスのインスタンス側を編集して 93 00:07:00,200 --> 00:07:04,480 UniqueInstance とします。 U は大文字です。 94 00:07:06,720 --> 00:07:11,920 先ほどと同様に new を無効化して UniqueInstance を実装します。 95 00:07:12,080 --> 00:07:16,200 違いは U が大文字だということです。 96 00:07:18,080 --> 00:07:21,040 クラス変数を使った結果 97 00:07:22,120 --> 00:07:25,040 このクラス階層で唯一のシングルトンを 持つようになります。 98 00:07:25,240 --> 00:07:27,520 WebServer クラスに サブクラスが 3 つあるとすると 99 00:07:27,680 --> 00:07:32,080 WebServer とその 3 つのサブクラスが 同じシングルトンを共有することになります。 100 00:07:32,240 --> 00:07:35,680 したがって全体で 1 つの インスタンスを持つことになります。 101 00:07:36,640 --> 00:07:38,680 では、クラスの初期化についてです。 102 00:07:38,920 --> 00:07:43,720 クラスやインスタンスの間で共有される 変数を持つことができますが 103 00:07:43,920 --> 00:07:46,960 いずれかの時点で 値を与えてあげる必要があります。 104 00:07:47,800 --> 00:07:50,400 クラスを初期化する時です。 105 00:07:50,560 --> 00:07:55,160 オブジェクトは initialize メッセージが 送られた時に初期化されます。 106 00:07:55,320 --> 00:07:59,120 同様にクラスへ initialize メッセージを 送ることができます。 107 00:07:59,320 --> 00:08:04,240 initialize メソッドのコードで どのようにして変数を初期化するかを決めます。 108 00:08:05,840 --> 00:08:09,000 Color クラスを初期化したい場合は 109 00:08:09,320 --> 00:08:11,840 Color クラスに initialize メッセージを送ります。 110 00:08:12,680 --> 00:08:16,840 典型的にはバージョン管理システムが 111 00:08:17,160 --> 00:08:19,040 システムにクラスをロードした時に 112 00:08:19,280 --> 00:08:22,520 initialize メッセージが送られます。 113 00:08:22,880 --> 00:08:26,560 これは自動的に行われます。 ロードされたクラスそれぞれに 114 00:08:26,920 --> 00:08:28,960 手動でメッセージを送る必要はありません。 115 00:08:29,120 --> 00:08:31,120 しかし、クラスを実装する時に 116 00:08:31,320 --> 00:08:35,000 新しいクラスを式で定義した時には 117 00:08:35,400 --> 00:08:37,760 initialize メッセージを手動で 送る必要があります。 118 00:08:38,640 --> 00:08:41,280 ここに Color クラスの例があります。 119 00:08:41,480 --> 00:08:44,360 メタクラス側を見ています。 120 00:08:44,680 --> 00:08:49,000 いくつかのクラス変数や 121 00:08:50,320 --> 00:08:53,000 クラス側のインスタンス変数を 初期化しています。 122 00:08:53,240 --> 00:08:55,960 ここには両方のタイプの変数があります。 123 00:08:57,800 --> 00:08:59,680 initialize メソッドでは 124 00:08:59,880 --> 00:09:03,360 クラス側では super initialize は 使いません。 125 00:09:03,560 --> 00:09:07,880 インスタンス側で initialize メソッドを追加する場合には 126 00:09:08,080 --> 00:09:10,920 super initialize を使って系統的に 127 00:09:11,080 --> 00:09:15,320 新しく作られたオブジェクトの 全てのインスタンス変数を初期化します。 128 00:09:15,520 --> 00:09:16,760 しかしクラスの場合には 129 00:09:16,920 --> 00:09:22,000 initialize メッセージが送られた時点で 既にクラスやスーパークラスは存在しているので 130 00:09:22,160 --> 00:09:25,920 クラス側のinitialize メソッドでは super initialize はしません。 131 00:09:26,120 --> 00:09:29,760 さもないと クラスを何度も初期化してしまいます。 132 00:09:30,160 --> 00:09:31,680 覚えておくべきポイントです。 133 00:09:31,880 --> 00:09:35,640 状態を共有するためにはクラス変数を使います。 134 00:09:37,200 --> 00:09:41,000 クラスはオブジェクトで それぞれの変数を持つことができます。 135 00:09:41,160 --> 00:09:44,320 クラス側にもインスタンス変数があります。 136 00:09:45,000 --> 00:09:48,680 クラスを初期化するためには initialize メッセージを送って 137 00:09:48,840 --> 00:09:52,200 クラス側の initialize メソッドを 適用します。