aboutsummaryrefslogtreecommitdiff
path: root/files/ja/learn/javascript/objects/classes_in_javascript/index.html
blob: b0802b7072968e8017bf0275f99d79b5839455ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
---
title: JavaScript での継承
slug: Learn/JavaScript/Objects/Classes_in_JavaScript
tags:
  - Article
  - CodingScripting
  - Inheritance
  - JavaScript
  - OOJS
  - OOP
  - Object
  - Prototype
  - l10n:priority
  - 初心者
  - 学習
translation_of: Learn/JavaScript/Objects/Inheritance
original_slug: Learn/JavaScript/Objects/Inheritance
---
<div>{{LearnSidebar}}</div>

<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</div>

<p class="summary">OOJS のぞっとするような細部はほとんど説明されたので、ここでは”親”クラスからの機能を継承する”子供”のオブジェクトクラス (コンストラクタ) の生成方法について解説します。さらに、いつ、どこで OOJS を使うかについてのアドバイスを提示し、最新の ECMAScript の構文でクラスがどのように扱われるかを見ていきます。</p>

<table class="learn-box standard-table">
 <tbody>
  <tr>
   <th scope="row">前提知識</th>
   <td>基本的なコンピュータの知識および利用能力、HTML と CSS への基本的な理解、JavaScript の基本 (<a href="/ja/docs/Learn/JavaScript/First_steps">第一歩</a><a href="/ja/docs/Learn/JavaScript/Building_blocks">構成要素</a>を参照) と OOJS の基本 (<a href="/ja/docs/Learn/JavaScript/Objects/Basics">オブジェクト入門</a>) に慣れている。</td>
  </tr>
  <tr>
   <th scope="row">目的:</th>
   <td>JavaScript でどのように継承ができるようになっているかを理解していること。</td>
  </tr>
 </tbody>
</table>

<h2 id="Prototypal_inheritance" name="Prototypal_inheritance">プロトタイプでの継承</h2>

<p>ここまで動作している継承 ー プロトタイプチェーンがどのように動作するか、どのようにメンバーが繋がるチェーンから継承されるのかを見てきました。しかし、これらの大半はブラウザーの組み込み関数で実行されています。我々が他のオブジェクトから継承したオブジェクトを作成するには JavaScript でどのようにするのでしょうか。</p>

<p>具体的な例を使ってどのようの継承が行われているかを見てゆきましょう。</p>

<h2 id="Getting_started" name="Getting_started">さあ始めてみよう</h2>

<p>まず、<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-start.html">oojs-class-inheritance-start.html</a> ファイルをローカルにコピーしましょう (あるいは<a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-start.html">ライブ版の実行</a>でも確認できます)。ここでこのモジュールで幅広く使用されてきた <code>Person()</code> というコンストラクタの例を見つけることができます。わずかな違いがあって、コンストラクタ内部にプロパティのみが定義されています。</p>

<pre class="brush: js notranslate">function Person(first, last, age, gender, interests) {
  this.name = {
    first,
    last
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
};</pre>

<p>メソッドはすべてコンストラクタのプロトタイプとして定義されています。例えば、</p>

<pre class="brush: js notranslate">Person.prototype.greeting = function() {
  alert('Hi! I\'m ' + this.name.first + '.');
};</pre>

<div class="note">
<p><strong>注意</strong>: ソースコードに、<code>bio()</code> と <code>farewell()</code> が定義されています。後ほどこれらのメソッドがどのようにほかのコンストラクタで継承されるのかを確認します。</p>
</div>

<p><code>Teacher</code> クラスを作成したい場合を考えましょう。これは最初のオブジェクト指向の特徴にて述べたもののようなクラスで、<code>Person</code> からすべてのメンバーを継承しますが、次のものも内包しています。</p>

<ol>
 <li>新しいプロパティの <code>subject</code> — これはその先生の教える科目を格納します。</li>
 <li>上書きされた <code>greeting()</code> メソッド、標準の <code>greeting()</code> メソッドよりわずかに固く感じられる — 学校で生徒に語りかける先生により相応しい。</li>
</ol>

<h2 id="Defining_a_Teacher_constructor_function" name="Defining_a_Teacher_constructor_function">Teacher() コンストラクタの機能を定義しよう</h2>

<p>われわれのまずすべき事は <code>Teacher()</code> コンストラクタを作成する事です — 以下に続くコードを既存コードの下に追加してください。</p>

<pre class="brush: js notranslate">function Teacher(first, last, age, gender, interests, subject) {
  Person.call(this, first, last, age, gender, interests);

  this.subject = subject;
}</pre>

<p>これは多くの点で Person コンストラクタと似ていますが、これまでに見てきたものと異なったものがあります—  <code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call()</a></code> 関数です。この関数は基本的に別の場所で定義された関数を、しかし現在のコンテキストで呼び出すことができます。最初の引数は関数を実行するときに使用したい <code>this</code> の値を指定します、また他の引数は実行される関数に渡されるべき値です。</p>

<p><code>Teacher()</code> コンストラクタは継承元の <code>Person()</code> コンストラクタと同じ引数を取りたいため、 <code>call()</code> を呼び出して、すべての引き数を引数として渡します。</p>

<p>コンストラクタの最後の行は、先生が行うべきであり、一般の人が持たない新たな <code>subject</code>(授業) のプロパティを定義しています。</p>

<p>注意として、下記のソースのように、このようにシンプルにも書けます。</p>

<pre class="brush: js notranslate">function Teacher(first, last, age, gender, interests, subject) {
  this.name = {
    first,
    last
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
  this.subject = subject;
}</pre>

<p>しかしながらこれはただ改めてプロパティを再定義しているだけで、 <code>Person()</code> から継承していません、そのため、説明しようとしたポイントが伝わりません。またコード行数が多くもなります。</p>

<h3 id="Inheriting_from_a_constructor_with_no_parameters" name="Inheriting_from_a_constructor_with_no_parameters">引数なしのコンストラクタからの継承</h3>

<p>もし継承したコンストラクタがパラメータからプロパティの値を取得しない場合、 <code>call()</code> の呼び出しで追加の引数を指定する必要がないことを示しておきます。そのため、例えば、このような本当にシンプルなものがある場合、</p>

<pre class="brush: js notranslate">function Brick() {
  this.width = 10;
  this.height = 20;
}</pre>

<p>このように書くことで <code>width</code> と <code>height</code> プロパティを継承することができます(もちろん、下に挙げる数行のステップの様にすることもできます)。</p>

<pre class="brush: js notranslate">function BlueGlassBrick() {
  Brick.call(this);

  this.opacity = 0.5;
  this.color = 'blue';
}</pre>

<p> <code>call()</code> の中に <code>this</code> だけを記載していることに注意して下さい— 引数を介して親より設定されるどのプロパティも継承しないので他の引数は不要です。</p>

<h2 id="Setting_Teachers_prototype_and_constructor_reference" name="Setting_Teachers_prototype_and_constructor_reference">Teacher()のプロトタイプ とコンストラクタの参照への設定方法</h2>

<p>今まではすべて順調でしたが、1点問題があります。新しいコンストラクタを定義して、その中に 1 つの <code>prototype</code> プロパティを持たせ、これはデフォルトでただ自身のコンストラクタ関数への参照を保持しています。Person のコンストラクタの <code>prototype</code> プロパティへのメソッド群は持っていません。このことを見てみたいのならば <code>Object.getOwnPropertyNames(Teacher.prototype)</code>  をテキスト入力フィールドや JavaScript コンソールへ入力を試してみてください。そして再度入力する時には、<code>Teacher</code> を <code>Person</code> で置き換えてみてください。新しいコンストラクタもそれらのメソッドを継承していません。このことを確認するために、<code>Person.prototype.greeting</code> と <code>Teacher.prototype.greeting</code> の出力結果を比べてみてください。<code>Person()</code>  のプロトタイプに定義されたメソッドを継承するために <code>Teacher()</code> を生成する必要があります。ではどのようにすればよいのでしょうか。</p>

<ol>
 <li>前回追加した部分の下に以下の行を追加してみましょう:
  <pre class="brush: js notranslate">Teacher.prototype = Object.create(Person.prototype);</pre>
  ここで我々に馴染み深い <code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> に再度助けてもらいましょう。この場合に新しいオブジェクトを作ってそれを <code>Teacher.prototype</code> の値とするのに使います。新しいオブジェクトは <code>Person.prototype</code> を自身のプロトタイプとして保持し、それがゆえに(必要となる時には) <code>Person.prototype</code> 上で利用できるすべてのメソッドを継承します。</li>
 <li>先に進む前にもう一つやることがあります。<br>
  最後の行を追加した後、<code>Teacher.</code><code>prototype</code><code>constructor</code> プロパティは <code>Person()</code> と同じになりました。なぜなら、<code>Person.prototype</code> からプロパティを継承するオブジェクトを参照するように <code>Teacher.prototype</code> を設定しただけだからです。コードを保存し、ブラウザでページを読み込み、コンソールに <code>Teacher.prototype.constructor</code> と入力して確認してみてください。</li>
 <li>これは問題になるかもしれません、なので以下の内容をすぐに設定しましょう。 ソースコードにまた戻って最後に以下の行を追加しましょう。
  <pre class="brush: js notranslate">Object.defineProperty(Teacher.prototype, 'constructor', {
    value: Teacher,
    enumerable: false, // 'for in'ループで現れないようにする
    writable: true });</pre>
 </li>
 <li>ソースコードを保存およびページの再読み込みを行って、 <code>Teacher.prototype.constructor</code> と入力したならば <code>Teacher()</code> と返すでしょう、希望した通りに <code>Person()</code> から継承することができました!</li>
</ol>

<h2 id="Giving_Teacher_a_new_greeting_function" name="Giving_Teacher_a_new_greeting_function">Teacher() に greeting() ファンクションを付け加える</h2>

<p>コードを完成させる前に、<code>Teacher()</code> コンストラクタに新たに <code>greeting()</code> 関数を追加する必要があります。</p>

<p>このようにする一番簡単な方法は <code>Teacher()</code> のプロトタイプに定義することです — コードの最後に以下のコードを追加します。</p>

<pre class="brush: js notranslate">Teacher.prototype.greeting = function() {
  let prefix;

  if (this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') {
    prefix = 'Mr.';
  } else if (this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') {
    prefix = 'Mrs.';
  } else {
    prefix = 'Mx.';
  }

  alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.');
};</pre>

<p>これは性別を基にした適切な敬称を使う教師の挨拶を通知します。条件文を使うことで実現します。</p>

<h2 id="Trying_the_example_out" name="Trying_the_example_out">例を試してみよう</h2>

<p>これまでのコードをすべて入力し終えているなら、ソースコード(もしくはあなたの用意した同じようなコードに)の最後に続けて <code>Teacher()</code> からオブジェクトインスタンスを生成してみましょう。</p>

<pre class="brush: js notranslate">let teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');</pre>

<p>保存し、再読み込みをしたなら、新たな <code>teacher1</code> オブジェクトのプロパティとメソッドにアクセスしてみましょう、例えば。</p>

<pre class="brush: js notranslate">teacher1.name.first;
teacher1.interests[0];
teacher1.bio();
teacher1.subject;
teacher1.greeting();
teacher1.farewell();</pre>

<p>これらはすべて正常に動作するはずです。1, 2, 3, 6 行目のクエリは、ジェネリックな <code>Person()</code> コンストラクタ (クラス) から継承されたメンバにアクセスします。4 行目のクエリは、より特殊な <code>Teacher()</code> コンストラクタ (クラス) でのみ利用可能なメンバにアクセスしています。5 行目のクエリは <code>Person()</code> から継承したメンバにアクセスしていますが、<code>Teacher()</code> には同じ名前の独自のメンバがあるため、そのメンバにアクセスしています。</p>

<div class="note">
<p><strong>注記</strong>: もしここまでの例がうまく動作しないなら、あなたのコードと<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-finished.html">完成版</a>(<a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">ライブ版</a>も参照)を比較してみてください。</p>
</div>

<p>ここで述べている手法は JavaScript でクラスを継承する唯一の方法ではなく、問題なく動作し、JavaScript でのどのように実装するかの良いアイデアを提示しています。</p>

<p>また JavaScript でより明瞭に継承を行えるようにした新しい{{glossary("ECMAScript")}}の機能(<a href="/ja/docs/Web/JavaScript/Reference/Classes">Classes</a> を参照)にも興味を持つかもしれません。ここではそれらについて言及はしませんでした、それはまだブラウザー間で幅広くサポートされていないためです。一連の記事で検討してきた他のコード構造はすべて、IE9 やそれ以前のバージョンといった、はるか以前よりサポートされており、それより早くからのサポートを確認する方法となります。</p>

<p>一般的な方法は JavaScript ライブラリを使用することです — よく知られた選択肢のうちの大部分は、よりたやすく素早く利用できる簡易な機能セットを持っています。例えば <a href="http://coffeescript.org/#classes">CoffeeScript</a> は <code>class</code>, <code>extends</code> などを提供します。</p>

<h2 id="A_further_exercise" name="A_further_exercise">追加の特訓</h2>

<p><a href="/ja/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters">OOP 理論のセクション</a>では、概念として <code>Student</code> クラスも取り上げました。このクラスは <code>Person</code> のすべての機能を継承しており、また <code>Person</code> とは異なる <code>Teacher</code> の greeting よりもはるかにくだけた <code>greeting()</code> メソッドを持っています。このセクションで生徒の挨拶がどのように見えるかを見て、<code>Person()</code> のすべての機能を継承し、異なる <code>greeting()</code> 関数を実装した独自の <code>Student()</code> コンストラクタを実装してみてください。</p>

<div class="note">
<p><strong>注記</strong>: もしここまでの例がうまく動作しないなら、あなたのコードと<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-finished.html">完成版</a>(<a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">動作するライブ版</a>も参照)を比較してみてください。</p>
</div>

<h2 id="Object_member_summary" name="Object_member_summary">Object メンバーの概要</h2>

<p>要約すると、気になるプロパティ/メソッドは4種類あります。</p>

<ol>
 <li>コンストラクタ関数の内部で定義され、オブジェクトインスタンスに与えられるもの。独自のカスタムコードでは、コンストラクタの内部で <code>this.x = x</code> 型の行を使用して定義されたメンバです。組み込みのブラウザコードでは、オブジェクトインスタンス (通常は <code>new</code> キーワードを使用してコンストラクタを呼び出すことで作成されます。例:  <code>let myInstance = new myConstructor()</code>) のみが利用可能なメンバです</li>
 <li>コンストラクタ自身で直接定義されたもので、コンストラクタ上でのみ利用可能なもの。これらは一般的に組み込みのブラウザオブジェクトでのみ利用可能であり、インスタンスではなくコンストラクタに直接連結されていることで認識されます。たとえば <code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code> などです。これらは<strong>静的プロパティ/メソッド</strong>としても知られています</li>
 <li>コンストラクタのプロトタイプに定義されているもので、すべてのインスタンスに継承され、オブジェクトクラスを継承しているもの。これらには、コンストラクタの <code>prototype</code> プロパティに定義されている任意のメンバ (例: <code>myConstructor.prototype.x()</code>) が含まれます</li>
 <li>これらは、上で見たようにコンストラクタがインスタンス化されたときに作成されるオブジェクト (例えば <code>let teacher1 = new Teacher('Chris');</code> の後に <code>teacher1.name</code>)、またはオブジェクトリテラル (<code>let teacher1 = { name : 'Chris' }</code> の後に <code>teacher1.name</code>) のいずれかであることができます</li>
</ol>

<p>もしどれがどれを指すかを区別できないのであれば、まだ気にしないでください — あなたはまだ学習中で、実践を通じて精通することでしょう。</p>

<h2 id="ECMAScript_2015_Classes" name="ECMAScript_2015_Classes">ECMAScript 2015 のクラス</h2>

<p>ECMAScript 2015では、C++ や Java のクラスに似た、より簡単で洗練された構文を使用して再利用可能なクラスを記述する方法として、JavaScript に<a href="/ja/docs/Web/JavaScript/Reference/Classes">クラス構文</a>を導入しています。このセクションでは、Person と Teacher の例をプロトタイプの継承からクラスに変更して、どのようにして行うかを示します。</p>

<div class="note">
<p><strong>メモ</strong>: この近代的なクラスの作成方法は現在のすべてのブラウザでサポートされていますが、この構文をサポートしていないブラウザ (特に Internet Explorer) をサポートする必要があるプロジェクトで作業する場合に備えて、基本的なプロトタイプの継承の仕組みについて知っておくことはまだ価値があります。</p>
</div>

<p>Person の例を class-style で書き直したバージョンを見てみましょう:</p>

<pre class="brush: js line-numbers  language-js notranslate"><code class="language-js"><span class="keyword token">class</span> <span class="class-name token">Person</span> <span class="punctuation token">{</span>
  <span class="function token">constructor</span><span class="punctuation token">(</span>first<span class="punctuation token">,</span> last<span class="punctuation token">,</span> age<span class="punctuation token">,</span> gender<span class="punctuation token">,</span> interests<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>name <span class="operator token">=</span> <span class="punctuation token">{</span>
      first<span class="punctuation token">,</span>
      last
    <span class="punctuation token">}</span><span class="punctuation token">;</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>age <span class="operator token">=</span> age<span class="punctuation token">;</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>gender <span class="operator token">=</span> gender<span class="punctuation token">;</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>interests <span class="operator token">=</span> interests<span class="punctuation token">;</span>
  <span class="punctuation token">}</span>

  <span class="function token">greeting</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
    console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="template-string token"><span class="string token">`Hi! I'm </span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span><span class="keyword token">this</span><span class="punctuation token">.</span>name<span class="punctuation token">.</span>first<span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">`</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span>
  <span class="punctuation token">}</span><span class="punctuation token">;</span>

  <span class="function token">farewell</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
    console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="template-string token"><span class="string token">`</span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span><span class="keyword token">this</span><span class="punctuation token">.</span>name<span class="punctuation token">.</span>first<span class="interpolation-punctuation punctuation token">}</span></span><span class="string token"> has left the building. Bye for now!`</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span>
  <span class="punctuation token">}</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span></code></pre>

<p><a href="/ja/docs/Web/JavaScript/Reference/Statements/class">class</a>ステートメントは、新しいクラスを作成していることを示します。 このブロックの中で、クラスのすべての機能を定義します。</p>

<ul>
 <li><code><a href="/ja/docs/Web/JavaScript/Reference/Classes/constructor">constructor()</a></code> メソッドは、<code>Person</code>クラスを表すコンストラクタ関数を定義します</li>
 <li><code>greeting()</code> と <code>farewell()</code> はクラスメソッドです。クラスに関連付けたいメソッドは、コンストラクタの後に定義されます。この例では、コードを読みやすくするために、文字列連結ではなく<a href="/ja/docs/Web/JavaScript/Reference/template_strings">テンプレート文字列</a>を使用しています</li>
</ul>

<p>以前と同じように<a href="/ja/docs/Web/JavaScript/Reference/Operators/new">new演算子</a>を使用してオブジェクトインスタンスをインスタンス化できるようになりました。</p>

<pre class="brush: js line-numbers  language-js notranslate"><code class="language-js"><span class="keyword token">let</span> han <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Person</span><span class="punctuation token">(</span><span class="string token">'Han'</span><span class="punctuation token">,</span> <span class="string token">'Solo'</span><span class="punctuation token">,</span> <span class="number token">25</span><span class="punctuation token">,</span> <span class="string token">'male'</span><span class="punctuation token">,</span> <span class="punctuation token">[</span><span class="string token">'Smuggling'</span><span class="punctuation token">]</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
han<span class="punctuation token">.</span><span class="function token">greeting</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="comment token">// Hi! I'm Han</span>

<span class="keyword token">let</span> leia <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Person</span><span class="punctuation token">(</span><span class="string token">'Leia'</span><span class="punctuation token">,</span> <span class="string token">'Organa'</span><span class="punctuation token">,</span> <span class="number token">19</span><span class="punctuation token">,</span> <span class="string token">'female'</span><span class="punctuation token">,</span> <span class="punctuation token">[</span><span class="string token">'Government'</span><span class="punctuation token">]</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
leia<span class="punctuation token">.</span><span class="function token">farewell</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="comment token">// Leia has left the building. Bye for now</span></code></pre>

<div class="note">
<p><strong>メモ</strong>: 内部ではクラスはプロトタイプの継承モデルに変換されています。これはシンタックスシュガーです。しかし、私たちはあなたがそれを書く方が簡単だと考えるだろうと確信しています。</p>
</div>

<h3 id="Inheritance_with_class_syntax" name="Inheritance_with_class_syntax">クラス構文による継承</h3>

<p>上記では人を表すクラスを作成しました。彼らはすべての人々に共通の一連の属性を持っています。このセクションでは、特殊な<code>Teacher</code>クラスを作成し、現代のクラス構文を使用して<code>Person</code>から継承します。これはサブクラス、またはサブクラスの作成と呼ばれます。<br>
 <br>
 サブクラスを作成するには <a href="/ja/docs/Web/JavaScript/Reference/Classes/extends">extends キーワード</a>を使用して、クラスの基底となるクラスをJavaScriptに通知します。</p>

<pre class="brush: js notranslate">constructor(first, last, age, gender, interests) {
   this.name = {
     first,
     last
   };
   this.age = age;
   this.gender = gender;
   this.interests = interests;
} </pre>

<p><a href="/ja/docs/Web/JavaScript/Reference/Operators/super"><code>super()</code></a> 演算子を <code>constructor()</code> 内の最初の項目として定義することで、コードをより読みやすくすることができます。これは親クラスのコンストラクタを呼び出し、そこに定義されている限り、指定したメンバーを<code>super()</code> のパラメータとして継承します。</p>

<pre class="brush: js line-numbers  language-js notranslate"><code class="language-js"><span class="keyword token">class</span> <span class="class-name token">Teacher</span> <span class="keyword token">extends</span> <span class="class-name token">Person</span> <span class="punctuation token">{</span>
  <span class="function token">constructor</span><span class="punctuation token">(</span>first<span class="punctuation token">,</span> last<span class="punctuation token">,</span> age<span class="punctuation token">,</span> gender<span class="punctuation token">,</span> interests<span class="punctuation token">,</span> subject<span class="punctuation token">,</span> grade<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">super</span><span class="punctuation token">(</span>first<span class="punctuation token">,</span> last<span class="punctuation token">,</span> age<span class="punctuation token">,</span> gender<span class="punctuation token">,</span> interests<span class="punctuation token">)</span><span class="punctuation token">;</span>

    <span class="comment token">// 科目と学年は教師によって決まっている</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>subject <span class="operator token">=</span> subject<span class="punctuation token">;</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>grade <span class="operator token">=</span> grade<span class="punctuation token">;</span>
  <span class="punctuation token">}</span>
<span class="punctuation token">}</span></code></pre>

<p><code>Teacher</code>のオブジェクトをインスタンス化するときには、<code>Teacher</code><code>Person</code>の両方で定義されたメソッドとプロパティを呼び出すことができます。</p>

<pre class="brush: js line-numbers  language-js notranslate"><code class="language-js"><span class="keyword token">let</span> snape <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Teacher</span><span class="punctuation token">(</span><span class="string token">'Severus'</span><span class="punctuation token">,</span> <span class="string token">'Snape'</span><span class="punctuation token">,</span> <span class="number token">58</span><span class="punctuation token">,</span> <span class="string token">'male'</span><span class="punctuation token">,</span> <span class="punctuation token">[</span><span class="string token">'Potions'</span><span class="punctuation token">]</span><span class="punctuation token">,</span> <span class="string token">'Dark arts'</span><span class="punctuation token">,</span> <span class="number token">5</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
snape<span class="punctuation token">.</span><span class="function token">greeting</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// Hi! I'm Severus.</span>
snape<span class="punctuation token">.</span><span class="function token">farewell</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// Severus has left the building. Bye for now.</span>
snape<span class="punctuation token">.</span>age <span class="comment token">// 58</span>
snape<span class="punctuation token">.</span>subject<span class="punctuation token">;</span> <span class="comment token">// Dark arts</span></code></pre>

<p>Teachers と同じように、基本クラスを変更せずに <code>Person</code> をさらに特化したものにするために、他のサブクラスを作成できます。</p>

<div class="note">
<p><strong>メモ</strong>: この例は、GitHub で <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/es2015-class-inheritance.html">es2015-class-inheritance.html</a> として見つけることができます(<a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/es2015-class-inheritance.html">これも実際に参照してください</a>)。</p>
</div>

<h2 id="Getters_and_Setters" name="Getters_and_Setters">Getter と Setter</h2>

<p>作成するクラスの属性の値を変更したい場合や、属性の最終値がわからない場合があります。<code>Teacher</code> の例を使用すると、教師が教材を作成する前にどの教科を教えるか分からないことがあります。<br>
 <br>
 getter や setter でこのような状況を処理できます。<br>
 <br>
 getter と setter で Teacher クラスを強化しましょう。私たちが最後に見たときと同じようにクラスが始まります。<br>
 <br>
 getter と setter はペアで動作します。getter は変数の現在の値を返し、対応する setter は変数の値をひとつの値に変更します。<br>
 <br>
 変更された <code>Teacher</code> クラスは次のようになります。</p>

<pre class="brush: js line-numbers  language-js notranslate"><code class="language-js"><span class="keyword token">class</span> <span class="class-name token">Teacher</span> <span class="keyword token">extends</span> <span class="class-name token">Person</span> <span class="punctuation token">{</span>
  <span class="function token">constructor</span><span class="punctuation token">(</span>first<span class="punctuation token">,</span> last<span class="punctuation token">,</span> age<span class="punctuation token">,</span> gender<span class="punctuation token">,</span> interests<span class="punctuation token">,</span> subject<span class="punctuation token">,</span> grade<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">super</span><span class="punctuation token">(</span>first<span class="punctuation token">,</span> last<span class="punctuation token">,</span> age<span class="punctuation token">,</span> gender<span class="punctuation token">,</span> interests<span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="comment token">// 科目と学年は教師によって決まっている</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>_subject <span class="operator token">=</span> subject<span class="punctuation token">;</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>grade <span class="operator token">=</span> grade<span class="punctuation token">;</span>
  <span class="punctuation token">}</span>

  <span class="keyword token">get</span> <span class="function token">subject</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">return</span> <span class="keyword token">this</span><span class="punctuation token">.</span>_subject<span class="punctuation token">;</span>
  <span class="punctuation token">}</span>

  <span class="keyword token">set</span> <span class="function token">subject</span><span class="punctuation token">(</span>newSubject<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>_subject <span class="operator token">=</span> newSubject<span class="punctuation token">;</span>
  <span class="punctuation token">}</span>
<span class="punctuation token">}</span></code></pre>

<p>上のクラスでは、<code>subject</code> プロパティの getter と setter があります。 Nameプロパティを格納するために <strong><code>_</code> </strong>を使用して別の値を作成します。この規約を使用しないと、get または set を呼び出すたびにエラーが発生します。 この時点で:</p>

<ul>
 <li><code>snape</code> オブジェクトの <code>_subject</code> プロパティの現在の値を表示するには、<code>snape.subject</code> getter メソッドを使用します</li>
 <li><code>_subject</code> プロパティに新しい値を割り当てるには、<code>snape.subject="new value"</code> setter メソッドを使用できます</li>
</ul>

<p>以下の例は、動作している2つの機能を示しています。</p>

<pre class="brush: js line-numbers  language-js notranslate"><code class="language-js"><span class="comment token">// デフォルトの値をチェックする</span>
console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>snape<span class="punctuation token">.</span>subject<span class="punctuation token">)</span> <span class="comment token">// Returns "Dark arts"</span>

<span class="comment token">// 値を変更する</span>
snape<span class="punctuation token">.</span>subject <span class="operator token">= </span><span class="string token">"Balloon animals"</span> <span class="comment token">// Sets _subject to "Balloon animals"</span>

<span class="comment token">// 新しい値と一致しているか再度チェックする</span>
console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>snape<span class="punctuation token">.</span>subject<span class="punctuation token">)</span> <span class="comment token">// Returns "Balloon animals"</span></code></pre>

<div class="note">
<p><strong>メモ</strong>: この例は、GitHub で <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/es2015-class-inheritance.html">es2015-class-inheritance.html</a> として見つけることができます(<a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/es2015-class-inheritance.html">これも実際に参照してください</a>)。</p>
</div>

<div class="blockIndicator note">
<p><strong>メモ</strong>: ゲッターやセッターは、プロパティが要求されたり設定されたりするたびにコードを実行したい場合など、非常に便利な場合があります。しかし、単純なケースでは、ゲッターやセッターを使用しないプレーンなプロパティアクセスで十分です。</p>
</div>

<h2 id="When_would_you_use_inheritance_in_JavaScript" name="When_would_you_use_inheritance_in_JavaScript">JavaScript でいつ継承を使用するのでしょうか?</h2>

<p>特にこの最後の記事を読み終えた後、「うーん、これはややこしいな。」と考えることでしょう。ええ、それは正しい感想です。プロトタイプと継承は JavaScript のもっとも複雑な面のいくつかに当たります、しかし多くの JavaScript の能力と柔軟性はそのオブジェクトの構造と継承に由来します、そしてそれがどのように動作するかは理解するに値します。</p>

<p>ある意味では、常に継承を使用しています。Web API の様々な機能、文字列や配列といったブラウザーに組み込まれたオブジェクトで定義されているメソッド/プロパティを使用するときはいつも、暗黙の内に継承を使用しています。</p>

<p>コードに継承を使用していることに関して、特に開始時には、そして小さなプロジェクトでは多分頻繁には使っていないでしょう。不要にも関わらず、継承のためだけにオブジェクトおよび継承を使用するのは時間の浪費です。しかしコードの母体が大きくなればなるほど、継承についての必要性が目に付きやすくなってきます。同じような機能を持ついくつものオブジェクトを作成していることに気付いた場合は、共有機能を持つ汎化オブジェクトタイプを作成し、特化オブジェクトタイプでそれらの機能を継承させるのがお手軽であり、便利です。</p>

<div class="note">
<p><strong>注記</strong>: プロトタイプチェーンなどを使って JavaScript が動作する方法のために、オブジェクト間での機能の共有をしばしば <strong>移譲</strong> と呼ぶ事があります。特化オブジェクトは汎化オブジェクトタイプから機能的に移譲されています。</p>
</div>

<p>継承を使用している時、継承をやたら多いレベルに行わないように、メソッドとプロパティをどこに定義したかを注意深く追跡し続けるようにアドバイスされるでしょう。組み込みブラウザーのオブジェクトのプロトタイプを一時的に変更するコードを書き始めることは可能ですが、実際に良い理由がないのであれば、そうすべきではありません。過剰な継承は終わりない混乱や、そんなコードをデバッグする時は終わりない痛みに繋がりかねません。</p>

<p>究極的には、オブジェクトは関数やループのような、自身の固有の役割や長所を活かした、コードの再利用の単なる別の形でもあります。もし関連のある変数や関数の一団を作成していることに気付き、それらすべてを追跡して適切にパッケージ化したいのであれば、オブジェクトは良いアイデアです。オブジェクトはまた、ある所から別の所にデータの集合を渡したい場合にも大変便利です。これらの事柄の両方がコンストラクタや継承を使用する事なく達成できます。もしオブジェクトの単一のインスタンスが必要なだけであれば、オブジェクトリテラルを使用するのが多分より良く、確実に継承は必要ないでしょう。</p>

<h2 id="Alternatives_for_extending_the_prototype_chain" name="Alternatives_for_extending_the_prototype_chain">プロトタイプチェーンを拡張するための代替案</h2>

<p>JavaScript では、上で示したものとは別に、オブジェクトのプロトタイプを拡張する方法がいくつかあります。その他の方法についての詳細は、<a href="/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Different_ways_to_create_objects_and_the_resulting_prototype_chain">継承とプロトタイプチェーン</a>の記事を参照してください。</p>

<h2 id="Test_your_skills!" name="Test_your_skills!">あなたのスキルをテストしてみましょう!</h2>

<p>この記事はここまでですが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するためのテストがいくつかあります - <a href="/ja/docs/Learn/JavaScript/Objects/Test_your_skills:_Object-oriented_JavaScript">あなたのスキルをテストする: オブジェクト指向 JavaScript</a> を参照してください。</p>

<h2 id="Summary" name="Summary">まとめ</h2>

<p>この記事は今知っておくべき考えられる OOJS の核となる理論および文法の残りの部分をカバーしています。この時点で、 JavaScript オブジェクトおよび オブジェクト指向プログラミングの基本、プロトタイプとプロトタイプにおける継承、クラス(コンストラクタ)とオブジェクトのインスタンスの生成、クラスへの機能の追加、他のクラスから継承されたサブクラスの生成をどのように行うか、を理解しているでしょう。</p>

<p>次の記事では JavaScript Object Notaion (JSON) 、つまり  JavaScript オブジェクトを使用して書かれた共通データ交換フォーマット、がどのように動作するかをを見て行きましょう。</p>

<h2 id="See_also" name="See_also">あわせて参照</h2>

<ul>
 <li><a href="http://www.objectplayground.com/">ObjectPlayground.com</a> — オブジェクトについて学べる非常に有益な会話型学習サイト</li>
 <li><a href="https://www.amazon.com/gp/product/193398869X/">Secrets of the JavaScript Ninja</a>, Chapter 6 — John Resig Bear Bibeault による、先進的な JavaScript のコンセプトおよび手法についての良書。6 章ではプロトタイプや継承の非常に有効な面が説明されている。多分プリントやオンラインのコピーを比較的簡単に追跡する事ができるでしょう。</li>
 <li><a href="https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&amp;%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes">You Don't Know JS: this &amp; Object Prototypes</a> — Kyle Simpson による JavaScript を説明したすぐれたシリーズの一部。特に 5 章はプロトタイプについて、我々の説明より相当詳細に説明しています。初心者向けのこのシリーズ記事では単純化した見方を提供してきましたが、いっぽう Kyle は非常に深く論じており、より複雑だがより正確な図を提供しています。</li>
</ul>

<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p>

<h2 id="In_this_module" name="In_this_module">このモジュール</h2>

<ul>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Basics">JavaScript オブジェクトの基本</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Object-oriented_JS">初心者のためのオブジェクト指向 JavaScript</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Object_prototypes">Object のプロトタイプ</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Inheritance">JavaScript での継承</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/JSON">JSON データの操作</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Object_building_practice">オブジェクト作成の練習</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">バウンスボールに機能を追加する</a></li>
</ul>