JavaScriptでは単一の継承しかできない等の他の言語との違いがあるため、オブジェクト指向設計の理解に苦労しています。
中でもインターフェースはどのように実現すればよいのでしょうか。
初学者であるため前提理解の無い抽象的な質問ではありますが、関連事項や連想される内容でも構いませんので回答よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/28 07:13
2020/02/28 07:16
2020/02/28 07:36
2020/02/28 09:18

回答3件
0
要件定義
まず、「インターフェース」を要件定義しましょう。
「JavaScriptにない用語」を他言語と同じように使うのは混乱の元です。
ECMAScript 2019
ES2019では「将来の予約語」に interface
があります。
この時点では、まだ使えません。
ES2019上に「Interface」の定義はありませんが、
文脈上で「Interface」を見ることは出来ます。
例えば、Iterable Interface
- 25.1.1.1 The Iterable Interface - ECMAScript® 2019 Language Specification
- Symbol.iterator - JavaScript | MDN
JavaScript
1Symbol.iterator
DOM Level 3 Core
DOMは複数言語に適用可能なモデルであり、「Interface」があります。
やや古いですが、DOM Level 3 Coreでは、ECMAScriptにおける実装手段に言及されています。
基本は関数オブジェクトですが、コンストラクタと非コンストラクタの二種類存在します。
JavaScript
1console.log(typeof DOMException, typeof Node); // "function" "function" 2 3console.log(new DOMException); // DOMExceptionのインスタンス 4new Node; // TypeError: Illegal constructor
プロトタイプベース言語は、[[Prototype]]
上にオブジェクトがあれば良いので、必ずしもコンストラクタ呼び出し出来る必要はありません。
JavaScript
1class Foo {} 2 3class Piyo { 4 constructor () { 5 throw new TypeError('Illegal constructor'); 6 } 7} 8 9console.log(new Foo); // Fooのインスタンス 10new Piyo; // TypeError: Illegal constructor
Re: kiahi39 さん
投稿2020/06/03 12:57
編集2020/06/03 13:02総合スコア18194
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
前提
インターフェースは共通の振る舞いを定義するものです。また、インターフェースはプログラム実行前に定める必要があります。プログラム実行中に変化されてはインターフェース(規格)としては当然使えなくなるのでプログラムを書く人が困ります。
よって、振る舞いが持つパラメータや戻り値には、静的な型 を指定しなければなりません。
静的な型
とは プログラムの実行前から一意に決まっている型 のことで、動的な型
とは 実行時の実際の値によって決まる型 のことです。静的な型を持つ言語はその性質上、コンパイルが必要な場合がほとんどです。
回答
JavaScript
は動的型付け言語なので、インターフェースを使用することができません。
インタフェースを利用した設計を行いたい場合は、C#
やJava
、TypeScript
のようなオブジェクト指向かつ静的型付けな言語を使用する必要があります。
#補足
hayataka2049 さんからのコメントを受け、回答内容を修正しました。
過去の回答はコメントからトレースできるよう下記に残します。
前提
オブジェクト指向には クラスベース
と プロトタイプベース
の2種類があります。
両者の違いはオブジェクトの生成方法です。クラスベースは クラスを通して生成(インスタンス化) します。プロトタイプベースは プロトタイプと呼ばれるオブジェクトをクローンして生成 します。
例えばC#
やJava
、TypeScript
のような言語はクラスベース、JavaScript
はプロトタイプベースのオブジェクト指向をサポートしています。
クラスベースな言語はクラスを定義する性質上、静的な型を取り扱います。プロトタイプベースな言語には 糖衣構文等で疑似的にサポートされている場合を除き、本質的にはクラスが存在せず、静的な型も持ちません。全て動的な型として扱います。
ここまでに述べた 静的な型
とは プログラムの実行前から一意に決まっている型 のことで、動的な型
とは 実行時の実際の値によって決まる型 のことです。静的な型を持つ言語はその性質上、コンパイルが必要な場合がほとんどです。
回答
インターフェースは内部に振る舞い(メソッド)を静的に定義します。よって、インターフェースを実装したオブジェクトは静的にその振る舞いを定義しなければなりません。
この性質上、JavaScript
のような動的な型しか扱わない言語、すなわちプロトタイプベースなオブジェクト指向言語では実現することができません。
インタフェースを利用した設計を行いたい場合は、クラスベースなオブジェクト指向言語を使用する必要があります。
投稿2020/02/28 09:56
編集2020/02/28 12:11総合スコア2663
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/28 10:59
2020/02/28 11:58

0
インターフェースは実現できますか?
Object.setPrototypeOf()
回答済みとなって久しいご質問でしたが、追記になります。
DOM Standardの IDL
に interface mixin
と示される実装を class ブロック構文でどのように実現しているのかを探っていたところ、Object.setPrototypeOf()
を利用すれば、以下のように、「振る舞い」を 別の class ブロックで定義できるようです。
javascript
1class AnyInterface { 2 3 increment() { 4 this.data++; 5 } 6 7 decrement() { 8 this.data--; 9 } 10 11} 12 13 14class MyClass { 15 16 constructor ( data = 0 ) { 17 this.data = data; 18 } 19 20} 21 22// mixin interface を実現? 23Object.setPrototypeOf( MyClass.prototype, AnyInterface.prototype ); 24 25// test 26let myClass = new MyClass( 3 ); 27console.log( myClass.data ); // 3 28 29myClass.increment(); 30console.log( myClass.data ); // 4 31 32myClass.decrement(); 33console.log( myClass.data ); // 3
以下、古い回答になります。
できないです。設計上はともかくとして、実装は不要と思います。
インターフェースは「変数やメソッドの定義忘れをコンパイラが解釈してエラー通知してくれる」という側面があると思いますが、JavaScriptではそのような実装はありません。
WikipediaのBuilderパターン にinterface / implements が例示されていましたので、javascript で示してみました。
- JapaneseHouseBuilder は単一継承で無理やりインターフェースを実装
(JavaScriptの成果物としては冗長になる)
- KamakuraBuilder は 抽象化の定義のみ
インターフェースを実装しようとすると、コード量が増えるため minify が推奨されるブラウザ環境では無駄になります。が、設計図書等には、必須な変数、メソッドであることを示せばいいと思います。
投稿2020/02/28 08:33
編集2020/06/03 11:13総合スコア5434
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。