{
    "componentChunkName": "component---src-templates-blog-post-jsx",
    "path": "/post/learn-inherit-pattern-from-coffeescript-and-typescript/",
    "result": {"data":{"site":{"siteMetadata":{"title":"WEB EGG","author":"Leko - CTO at Yuimedi"}},"markdownRemark":{"id":"728dddce-a35b-5049-aee0-64240045b53b","excerpt":"こんにちは。 最近、オライリー・ジャパンの 「JavaScript パターン――優れたアプリケーションのための作法」という本を読んでいます。 この本は、JavaScript でのコーディングパターンや、 Javascript…","html":"<p>こんにちは。<br>\n最近、オライリー・ジャパンの<br>\n「<a href=\"http://www.oreilly.co.jp/books/9784873114880/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">JavaScript パターン――優れたアプリケーションのための作法</a>」という本を読んでいます。</p>\n<p>この本は、JavaScript でのコーディングパターンや、 Javascript に限らず広義の意味での「パターン」を取り扱っている書籍です。</p>\n<p>この本の中に、<strong>クラシカルな継承パターン</strong>というものがあります。<br>\nクラシカルな継承パターンとは、ざっくり言うと</p>\n<blockquote>\n<p>JavaScript にクラスの概念は無いけれど、<br>\n長年クラスベースの言語を触ってきた人たちが js を触るときに馴染みやすいように、<br>\nクラスや継承のような機能を提供するパターン</p>\n</blockquote>\n<p>だと僕は解釈しました。</p>\n<p>このクラシカルな継承パターンを読んで、<br>\n<strong>CoffeeScript や TypeScript での class 記法や継承パターンは、js に変換するとどう表現されるのか</strong><br>\nが気になったため、調査してみました。</p>\n<!--more-->\n<h2 id=\"目標\" style=\"position:relative;\"><a href=\"#%E7%9B%AE%E6%A8%99\" aria-label=\"目標 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>目標</h2>\n<p>当記事の目標は、<br>\n<strong>JavaScript における「クラス」の概念と継承のパターンが分かるようになる</strong><br>\nことです。</p>\n<p>当記事では、CoffeeScript や TypeScript については、あまり深く触れませんのであらかじめご了承下さい。</p>\n<h2 id=\"javascript-には-class-や継承の概念は無い\" style=\"position:relative;\"><a href=\"#javascript-%E3%81%AB%E3%81%AF-class-%E3%82%84%E7%B6%99%E6%89%BF%E3%81%AE%E6%A6%82%E5%BF%B5%E3%81%AF%E7%84%A1%E3%81%84\" aria-label=\"javascript には class や継承の概念は無い permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>JavaScript には class や継承の概念は無い</h2>\n<p>当記事を読んでいる方ならご存知かと思いますが、<br>\nJavaScript はプロトタイプベースのオブジェクト指向言語であり、<br>\n<strong>クラスや継承という概念はありません</strong>。</p>\n<p>ここが js の癖となる点の１つだと思います。<br>\nしかし、クラスや継承といった技法が実現不可能なわけではなく、<br>\nプロトタイプを上手く用いることで<strong>クラスのようなオブジェクトを作るも</strong>、それらの<strong>継承も可能</strong>です。</p>\n<p>ただし、繰り返しになりますが<br>\n言語の概念として、クラスや継承が存在していないので、<br>\nあくまで<strong>それらに似た振る舞いを再現</strong>できる、というだけです。</p>\n<h2 id=\"javascript-パターンによる聖杯パターン\" style=\"position:relative;\"><a href=\"#javascript-%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%AB%E3%82%88%E3%82%8B%E8%81%96%E6%9D%AF%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3\" aria-label=\"javascript パターンによる聖杯パターン permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>「JavaScript パターン」による”聖杯パターン”</h2>\n<p>JavaScript パターンから引用すると、<br>\n「クラシカルな継承のパターン」の模範解答は、以下のようになります。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 継承を行う関数</span>\n<span class=\"token keyword\">var</span> inherit <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> <span class=\"token function-variable function\">F</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token constant\">C</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">P</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">F</span><span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> <span class=\"token class-name\">P</span><span class=\"token punctuation\">.</span>prototype\n    <span class=\"token class-name\">C</span><span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">F</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token constant\">C</span><span class=\"token punctuation\">.</span>uber <span class=\"token operator\">=</span> <span class=\"token class-name\">P</span><span class=\"token punctuation\">.</span>prototype\n    <span class=\"token class-name\">C</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span>constructor <span class=\"token operator\">=</span> <span class=\"token constant\">C</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\">// Personクラス(のようなオブジェクト(以下省略))</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n<span class=\"token class-name\">Parent</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">say</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name\n<span class=\"token punctuation\">}</span>\n<span class=\"token comment\">// Childクラス</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">Child</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name\n  <span class=\"token comment\">// 親のコンストラクタを拝借する</span>\n  <span class=\"token function\">Parent</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token comment\">// 継承</span>\n<span class=\"token function\">inherit</span><span class=\"token punctuation\">(</span>Child<span class=\"token punctuation\">,</span> Parent<span class=\"token punctuation\">)</span>\n<span class=\"token comment\">// インスタンスを作成</span>\n<span class=\"token keyword\">var</span> kid <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Child</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Bob'</span><span class=\"token punctuation\">)</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>kid<span class=\"token punctuation\">.</span><span class=\"token function\">say</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 'Bob'</span></code></pre></div>\n<p>上記のように、<br>\nChild クラスは、say メソッドを持っていませんが、<br>\nChild クラスのインスタンスである<code>kid</code>は、say メソッドを Parent クラスのプロトタイプから利用できます。</p>\n<p>明示的にクラスです！ と宣言する文法がないため、文法は他の言語と大きく異なりますが、<br>\nこれでおおよそクラスと継承の機構が再現出来ていると思います。</p>\n<p>クロージャを利用すれば、プライベートメンバー・メソッドが定義可能です。</p>\n<p>それはさておき、ここで重要なのが、継承のための関数<code>inherit()</code>です。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> inherit <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> <span class=\"token function-variable function\">F</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n  <span class=\"token comment\">// CとPのプロキシとなる関数F</span>\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token constant\">C</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">P</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">F</span><span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> <span class=\"token class-name\">P</span><span class=\"token punctuation\">.</span>prototype\n    <span class=\"token comment\">// Fのプロトタイプオブジェクトを親と共有する</span>\n    <span class=\"token class-name\">C</span><span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">F</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token comment\">// 子のプロトタイプオブジェクトは、Fのインスタンスを設定</span>\n    <span class=\"token constant\">C</span><span class=\"token punctuation\">.</span>uber <span class=\"token operator\">=</span> <span class=\"token class-name\">P</span><span class=\"token punctuation\">.</span>prototype\n    <span class=\"token comment\">// スーパークラス(uberという名前にする)には親のプロトタイプを設定</span>\n    <span class=\"token class-name\">C</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span>constructor <span class=\"token operator\">=</span> <span class=\"token constant\">C</span>\n    <span class=\"token comment\">// コンストラクタのポインタを再設定する</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>この inherit()は、</p>\n<ul>\n<li>親と子のプロトタイプの共有を切りつつ、プロトタイプ連鎖の利点は残す</li>\n<li>親のメンバー(this.XXX)を継承する</li>\n</ul>\n<p>ために、子と親をつなぐプロキシとなる関数 F()を作成します<br>\nこの関数 F を利用することで、プロトタイプの共有を切りつつも、親のメンバーを共有することが可能になります。</p>\n<p>※当記事は js でのコーディングパターンが主旨なので、<br>\njs のプロトタイプチェインについて詳しくは触れません。<br>\nプロトタイプ連鎖については、以下の記事が参考になるかと思います。</p>\n<ul>\n<li><a href=\"http://builder.japan.zdnet.com/script/sp_javascript-kickstart-2007/20369792/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">JavaScript のプロトタイプチェインをちゃんと理解する – builder</a></li>\n</ul>\n<h2 id=\"coffeescript-での-class-と継承\" style=\"position:relative;\"><a href=\"#coffeescript-%E3%81%A7%E3%81%AE-class-%E3%81%A8%E7%B6%99%E6%89%BF\" aria-label=\"coffeescript での class と継承 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Coffeescript での class と継承</h2>\n<p>お待たせしました。<br>\n長い前置きを終えて、本題です。</p>\n<p>CoffeeScript や Typescript などの言語では、<br>\nこれらのややこしくて面倒なことを気にせずに、<br>\n<strong>class~extends という文だけで js でクラス(のようなオブジェクト)を使用出来ます</strong>。</p>\n<p>CoffeeScript でクラスと継承を用いた例が、以下となります。<br>\n(CoffeeScript.org の<a href=\"http://coffeescript.org/#classes\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Classes</a>の説明から持ってきて一部改変)</p>\n<div class=\"gatsby-highlight\" data-language=\"coffeescript\"><pre class=\"language-coffeescript\"><code class=\"language-coffeescript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Parent</span>\n  <span class=\"token property\">constructor</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token class-member variable\">@name</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span>\n  <span class=\"token property\">move</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>meters<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span>\n    console<span class=\"token punctuation\">.</span>log <span class=\"token class-member variable\">@name</span> <span class=\"token operator\">+</span> <span class=\"token string\">\" moved <span class=\"token interpolation variable\">#{meters}</span>m.\"</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Child</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Parent</span>\n  <span class=\"token property\">move</span><span class=\"token operator\">:</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span>\n    console<span class=\"token punctuation\">.</span>log <span class=\"token string\">\"slithering…\"</span>\n    <span class=\"token keyword\">super</span> <span class=\"token number\">5</span>\n\nchild <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Child</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\nchild<span class=\"token punctuation\">.</span><span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>ものすごくシンプルです。<br>\nだって<code>class</code>とか<code>extends</code>って文法が使えるんですもん。</p>\n<p>たったこれだけで、クラスの定義と継承ができます。</p>\n<p>次は、TypeScript での例を見てみます。</p>\n<h2 id=\"typescript-での-class-と継承\" style=\"position:relative;\"><a href=\"#typescript-%E3%81%A7%E3%81%AE-class-%E3%81%A8%E7%B6%99%E6%89%BF\" aria-label=\"typescript での class と継承 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>TypeScript での class と継承</h2>\n<p>比較しやすいように、CoffeeScript の例と同じものを TypeScript で書き直しました。<br>\n※TypeScript はまだ初心者なので、書き違いがあったらすみません。</p>\n<p>TypeScript でのクラスの定義と継承の例は以下となります。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Parent</span> <span class=\"token punctuation\">{</span>\n  name<span class=\"token operator\">:</span> string\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name<span class=\"token operator\">:</span> string</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token function\">move</span><span class=\"token punctuation\">(</span>meters<span class=\"token operator\">:</span> number<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token keyword\">void</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">+</span> <span class=\"token string\">' moved '</span> <span class=\"token operator\">+</span> meters <span class=\"token operator\">+</span> <span class=\"token string\">'m.'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Child</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Parent</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token keyword\">void</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'slithering… '</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">.</span><span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">var</span> child<span class=\"token operator\">:</span> Child <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Child</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\nchild<span class=\"token punctuation\">.</span><span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>ややコード量が増えていますが、とても見やすいです。<br>\nTypeScript でも、<code>class</code>と<code>extends</code>を使用できます。</p>\n<p>CoffeeScript や TypeScirpt では、prototype だの継承だのといったややこしい処理は、<br>\njs にコンパイルする際に、<strong>特定の表現と、継承するための汎用関数を吐き出し</strong>て、それを利用しています。</p>\n<p>次に、この<code>特定の表現</code>と<code>汎用関数</code>がどう実装されているのかを見ていきます。</p>\n<h2 id=\"継承を行う汎用関数の比較\" style=\"position:relative;\"><a href=\"#%E7%B6%99%E6%89%BF%E3%82%92%E8%A1%8C%E3%81%86%E6%B1%8E%E7%94%A8%E9%96%A2%E6%95%B0%E3%81%AE%E6%AF%94%E8%BC%83\" aria-label=\"継承を行う汎用関数の比較 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>継承を行う汎用関数の比較</h2>\n<h3 id=\"coffeescript-バージョン\" style=\"position:relative;\"><a href=\"#coffeescript-%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3\" aria-label=\"coffeescript バージョン permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CoffeeScript バージョン</h3>\n<p>まずは CoffeeScript バージョンを見ていきます。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> __hasProp <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">.</span>hasOwnProperty<span class=\"token punctuation\">,</span>\n  <span class=\"token function-variable function\">__extends</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">child<span class=\"token punctuation\">,</span> parent</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> key <span class=\"token keyword\">in</span> parent<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">__hasProp</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> child<span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">]</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">function</span> <span class=\"token function\">ctor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>constructor <span class=\"token operator\">=</span> child\n    <span class=\"token punctuation\">}</span>\n    ctor<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">.</span>prototype\n    child<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ctor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    child<span class=\"token punctuation\">.</span>__super__ <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">.</span>prototype\n    <span class=\"token keyword\">return</span> child\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p><code>__hasProp</code>は、安全で確実に<code>Object.hasOwnProperty()</code>を呼ぶためのショートカットです。<br>\n肝心の継承する関数が、<code>__extends(child, parent)</code>です。</p>\n<p>JavaScript パターンの聖杯バージョンに出てきた<br>\n<code>inherit(Child, Parent)</code>と、順序は違うけれど似ていますね。</p>\n<p>inherit()と異なる点は、for 文を用いて<strong>親のメンバーを子にコピーしている</strong>箇所です。</p>\n<p>実はこのパターンも、JavaScript パターンで出てきます。<br>\n「プロパティのコピーによる継承」と題されており、<br>\nプロパティのコピーする関数<code>extend()</code>を実装しています。</p>\n<p>書籍のコード少し改造した例が以下となります。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">extend</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">parent<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> hasProp <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">.</span>hasOwnProperty<span class=\"token punctuation\">,</span>\n    p\n  child <span class=\"token operator\">=</span> child <span class=\"token operator\">||</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>p <span class=\"token keyword\">in</span> parent<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">hasProp</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      child<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">return</span> child\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>もうお分かりかと思いますが、Coffee 版に出てくる for 文と同じです。</p>\n<p>この<strong>extend()と、inherit()を合体させた関数</strong>が、<br>\nCoffeeScript における継承用の関数<code>__extends</code>となっています。</p>\n<h3 id=\"typescript-バージョン\" style=\"position:relative;\"><a href=\"#typescript-%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3\" aria-label=\"typescript バージョン permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>TypeScript バージョン</h3>\n<p>では、次に TypeScript バージョンを見てみます。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> __extends <span class=\"token operator\">=</span>\n  <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>__extends <span class=\"token operator\">||</span>\n  <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">d<span class=\"token punctuation\">,</span> b</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">function</span> <span class=\"token function\">__</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>constructor <span class=\"token operator\">=</span> d\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token class-name\">__</span><span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> b<span class=\"token punctuation\">.</span>prototype\n    d<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">__</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>TypeScript の方はややシンプルです。<br>\nですが、やっていることはほぼ変わりません。</p>\n<p>そしてさりげなく、__extends という<strong>関数が未定義の時のみ独自定義する</strong>といった気配りが入っています。</p>\n<p>TypeScript で継承する関数<code>__extends()</code>では、<br>\nJavaScript パターンでの<code>inherit()</code>を少し簡略化したものとなっています。</p>\n<h2 id=\"クラスの定義と-super-オブジェクト\" style=\"position:relative;\"><a href=\"#%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E5%AE%9A%E7%BE%A9%E3%81%A8-super-%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88\" aria-label=\"クラスの定義と super オブジェクト permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>クラスの定義と super オブジェクト</h2>\n<p>また、クラスの定義や、super(親クラスへの参照)の表現も調査してみました。<br>\nCoffeeScript も TypeScript もほぼ同様の表現になっています。</p>\n<p>下記は CoffeeScript の先程の例のクラス部分を js にコンパイルしたコードです。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> Parent <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">function</span> <span class=\"token function\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">move</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">meters</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">+</span> <span class=\"token string\">' moved '</span> <span class=\"token operator\">+</span> meters <span class=\"token operator\">+</span> <span class=\"token string\">'m.'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">return</span> Parent\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">var</span> Child <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">_super</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">__extends</span><span class=\"token punctuation\">(</span>Child<span class=\"token punctuation\">,</span> _super<span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">function</span> <span class=\"token function\">Child</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">_super</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">,</span> arguments<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token class-name\">Child</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">move</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'slithering… '</span><span class=\"token punctuation\">)</span>\n    <span class=\"token class-name\">_super</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function\">move</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">return</span> Child\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>Parent<span class=\"token punctuation\">)</span></code></pre></div>\n<p>まず、<code>var クラス名 = (function() {})();</code>とクラスの定義を即時関数に包み、<br>\nその中で<code>function クラス名()</code>と関数を<strong>再定義</strong>しています。<br>\nこれにより、今後コンストラクタ関数(クラス名)を呼び出す際には、<strong>内側の関数が呼び出されます</strong>。</p>\n<p>継承する子クラスでは、即時関数の引数に<code>_super</code>を取っています。<br>\nこの_super は、親クラスのコンストラクタ関数を指しています。<br>\nこの親コンストラクタ関数を、継承する関数<strong>extends を通じて、 子クラスの</strong>super__オブジェクトに設定しています。</p>\n<p>そして、<strong>super</strong>オブジェクトを経由して、<br>\n子クラスから親クラスのプロトタイプ上に存在するプロパティを利用します。</p>\n<p>この書き方は TypeScript でもほぼ同様の表現になっており、</p>\n<ul>\n<li>_super を<strong>super</strong>等のオブジェクトに格納せずに直接使う</li>\n<li>用いている変数名が若干異なる</li>\n</ul>\n<p>程度の違いがありますが、同様のパターンとみなすことができます。</p>\n<h2 id=\"まとめ\" style=\"position:relative;\"><a href=\"#%E3%81%BE%E3%81%A8%E3%82%81\" aria-label=\"まとめ permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>まとめ</h2>\n<p>js で、継承するためには、</p>\n<ul>\n<li>親と子のプロキシとなる関数(CoffeeScript では<code>ctor()</code>、TypeScript では<code>__()</code>)を定義</li>\n<li>プロキシ関数の prototype に親の prototype を設定</li>\n<li>子の prototype にプロキシ関数のインスタンスを設定</li>\n</ul>\n<p>の３ステップが最低限必要となります。 ここに、上乗せとして</p>\n<ul>\n<li>コンストラクタのポインタを再設定</li>\n<li>親から子へプロパティのコピー</li>\n</ul>\n<p>などが乗っかって来るようです。</p>\n<p>また、クラスの表現方法は、<br>\nCoffeeScript、TypeScript 共にほぼ同じなので、 上記のような書き方をしておくのがベターだと思います。</p>\n<p>なお、今回は<br>\n<strong>クラスのようなオブジェクトと継承の表現</strong>について書きましたが、</p>\n<p>JavaScript には prototype を用いた柔軟な継承の表現が他にもあります。<br>\n今回の例はあくまで<strong>js で”クラス”っぽいことがやりたい人</strong>向けの内容であることをご留意下さい。</p>","timeToRead":11,"frontmatter":{"title":"CoffeescriptとTypescriptから学ぶjsでのクラス・継承パターン","tags":["JavaScript"],"date":"May 09, 2013","featuredImage":{"childImageSharp":{"fluid":{"tracedSVG":"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='400'%20height='143'%20viewBox='0%200%20400%20143'%20preserveAspectRatio='none'%3e%3cpath%20d='M43%2048v16h57l-3%202-7%204a3526%203526%200%2001-22%2011%20105%20105%200%2000-21%2022c-2%201%200%204%202%204l7-2c7-4%2017-3%2015%201l1%201c2-1%203%205%202%208%200%201%200%202%201%201l3%202h4l6%201c3%202%208%202%205%200-1-1%200-1%202-1l4-1-4-1h-2c1-2%201-2-2-1-4%200-7-1-9-4l-1-3%204-4%204-2c1%202%2010-2%2014-6%207-6%209-12%207-23l-1-4-1-1-2-3c-1-4%200-5%203-5%201-1%202%200%203%202%200%202%201%202%206%202h5V31H43v17'%20fill='%23d3d3d3'%20fill-rule='evenodd'/%3e%3c/svg%3e","aspectRatio":2.783333333333333,"src":"/static/83eb668731704ae594b04d3d29ed7c2c/69e52/featured-image.png","srcSet":"/static/83eb668731704ae594b04d3d29ed7c2c/1ec58/featured-image.png 334w,\n/static/83eb668731704ae594b04d3d29ed7c2c/69e52/featured-image.png 569w","srcWebp":"/static/83eb668731704ae594b04d3d29ed7c2c/3d427/featured-image.webp","srcSetWebp":"/static/83eb668731704ae594b04d3d29ed7c2c/cd98f/featured-image.webp 334w,\n/static/83eb668731704ae594b04d3d29ed7c2c/3d427/featured-image.webp 569w","sizes":"(max-width: 569px) 100vw, 569px"}}}}}},"pageContext":{"slug":"/learn-inherit-pattern-from-coffeescript-and-typescript/","previous":{"fields":{"slug":"/event-report-of-js-app-in-tanemaki/"},"frontmatter":{"title":"第一回 JS-App勉強会@タネマキ LTメモ","tags":["angular.js","Backbone.js","CoffeeScript","Grunt","knockout.js","Nodejs"]}},"next":{"fields":{"slug":"/aoj-1137-numeral-system/"},"frontmatter":{"title":"[AOJ] 1137 Numeral System","tags":["AOJ","JavaScript"]}}}},
    "staticQueryHashes": ["2585454260","2954598359"]}