質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.06%

JavaScriptでオブジェクト指向におけるインターフェースは実現できますか?

解決済

回答 3

投稿

  • 評価
  • クリップ 3
  • VIEW 1,116

score 22

JavaScriptでは単一の継承しかできない等の他の言語との違いがあるため、オブジェクト指向設計の理解に苦労しています。
中でもインターフェースはどのように実現すればよいのでしょうか。

初学者であるため前提理解の無い抽象的な質問ではありますが、関連事項や連想される内容でも構いませんので回答よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • hoshi-takanori

    2020/02/28 16:16

    JavaScript ではダックタイピングができるので、インターフェイスなんてものは不要です。
    https://kazu-yamamoto.hatenablog.jp/entry/20071121/1195610224

    キャンセル

  • coco_bauer

    2020/02/28 16:36

    「オブジェクト指向設計の理解に苦労」というのは、何を対象とした、どのような設計において、何の理解をしようとしている時に発生したものなのですか?
    オブジェクト指向の言語について、どのぐらいの種類の言語を知っていらっしゃって、それらを使ってどのようなアプリケーションを構築した経験(苦労した経験)をお持ちなのですか?

    キャンセル

  • miyabi_takatsuk

    2020/02/28 18:18

    JavaScriptは動的型付けなので、実装できたとしても、あんまし効力ないと思います。
    どうしても、インターフェースを使いながらやりたいとなれば、TypeScriptでの開発をお勧めします。

    キャンセル

回答 3

+5

要件定義

まず、「インターフェース」を要件定義しましょう。
「JavaScriptにない用語」を他言語と同じように使うのは混乱の元です。

ECMAScript 2019

ES2019では「将来の予約語」に interface があります。
この時点では、まだ使えません。

ES2019上に「Interface」の定義はありませんが、

文脈上で「Interface」を見ることは出来ます。
例えば、Iterable Interface

Symbol.iterator

DOM Level 3 Core

DOMは複数言語に適用可能なモデルであり、「Interface」があります。
やや古いですが、DOM Level 3 Coreでは、ECMAScriptにおける実装手段に言及されています。

基本は関数オブジェクトですが、コンストラクタと非コンストラクタの二種類存在します。

console.log(typeof DOMException, typeof Node); // "function" "function"

console.log(new DOMException); // DOMExceptionのインスタンス
new Node; // TypeError: Illegal constructor

プロトタイプベース言語は、[[Prototype]] 上にオブジェクトがあれば良いので、必ずしもコンストラクタ呼び出し出来る必要はありません。

class Foo {}

class Piyo {
  constructor () {
    throw new TypeError('Illegal constructor');
  }
}

console.log(new Foo); // Fooのインスタンス
new Piyo; // TypeError: Illegal constructor

Re: kiahi39 さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+4

前提

インターフェースは共通の振る舞いを定義するものです。また、インターフェースはプログラム実行前に定める必要があります。プログラム実行中に変化されてはインターフェース(規格)としては当然使えなくなるのでプログラムを書く人が困ります。

よって、振る舞いが持つパラメータや戻り値には、静的な型 を指定しなければなりません。

静的な型 とは プログラムの実行前から一意に決まっている型 のことで、動的な型 とは 実行時の実際の値によって決まる型 のことです。静的な型を持つ言語はその性質上、コンパイルが必要な場合がほとんどです。

回答

JavaScript は動的型付け言語なので、インターフェースを使用することができません。

インタフェースを利用した設計を行いたい場合は、C#JavaTypeScript のようなオブジェクト指向かつ静的型付けな言語を使用する必要があります。

補足

hayataka2049 さんからのコメントを受け、回答内容を修正しました。
過去の回答はコメントからトレースできるよう下記に残します。


前提

オブジェクト指向には クラスベース と プロトタイプベース の2種類があります。

両者の違いはオブジェクトの生成方法です。クラスベースは クラスを通して生成(インスタンス化) します。プロトタイプベースは プロトタイプと呼ばれるオブジェクトをクローンして生成 します。

例えばC#JavaTypeScript のような言語はクラスベース、JavaScript はプロトタイプベースのオブジェクト指向をサポートしています。

クラスベースな言語はクラスを定義する性質上、静的な型を取り扱います。プロトタイプベースな言語には 糖衣構文等で疑似的にサポートされている場合を除き、本質的にはクラスが存在せず、静的な型も持ちません。全て動的な型として扱います。

ここまでに述べた 静的な型 とは プログラムの実行前から一意に決まっている型 のことで、動的な型 とは 実行時の実際の値によって決まる型 のことです。静的な型を持つ言語はその性質上、コンパイルが必要な場合がほとんどです。

回答

インターフェースは内部に振る舞い(メソッド)を静的に定義します。よって、インターフェースを実装したオブジェクトは静的にその振る舞いを定義しなければなりません。

この性質上、JavaScript のような動的な型しか扱わない言語、すなわちプロトタイプベースなオブジェクト指向言語では実現することができません。

インタフェースを利用した設計を行いたい場合は、クラスベースなオブジェクト指向言語を使用する必要があります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/02/28 19:59

    クラスベース/プロトタイプベースと静的型付け/動的型付けは直接関連する問題でしょうか? たとえばRubyは動的型付けでクラスベースなので、反例になりそうです。
    # 変数に型があるかどうか、であってオブジェクト指向の実現方法は問題ではない気がしますが・・・もちろんクラスベースはクラスを型とみなせるので静的型付けに親和性があるとは言えるにせよ

    キャンセル

  • 2020/02/28 20:20

    Ruby がクラスベースかつ動的型付けな言語とは知りませんでした。クラスペースと静的型付け、プロトタイプベースと動的型付けのペアは密接な関係(ほぼイコール)にあると認識していましたが、そこが勘違いだったようです。

    仰る通り、問題が混同していたので内容を整理します。ありがとうございます。

    キャンセル

  • 2020/02/28 20:58

    静的片付け・プロトタイプベースという組み合わせはたぶん存在しないのと、動的型付け・クラスベースはクラスもインスタンスであるという方向に進んで行くとプロトタイプベース風になるので、たぶん密接に関わる問題ではあります。ただ、今回の回答の主旨からすると静的型付け/動的型付けに絞って議論した方がいいのでは。

    キャンセル

  • 2020/02/28 21:13

    > 静的型付け/動的型付けに絞って議論した方がいいのでは。

    修正しました。 過去の回答は残しています。

    キャンセル

+4

インターフェースは実現できますか?

Object.setPrototypeOf()

回答済みとなって久しいご質問でしたが、追記になります。

DOM Standardの IDL に interface mixin と示される実装を class ブロック構文でどのように実現しているのかを探っていたところ、Object.setPrototypeOf() を利用すれば、以下のように、「振る舞い」を 別の class ブロックで定義できるようです。

class AnyInterface {

  increment() {
    this.data++;
  }

  decrement() {
    this.data--;
  }

}


class MyClass {

  constructor ( data = 0 ) {
    this.data = data;
  }

}

// mixin interface を実現?
Object.setPrototypeOf( MyClass.prototype, AnyInterface.prototype );

// test
let myClass = new MyClass( 3 );
console.log( myClass.data ); // 3

myClass.increment();
console.log( myClass.data ); // 4

myClass.decrement();
console.log( myClass.data ); // 3

以下、古い回答になります。

できないです。設計上はともかくとして、実装は不要と思います。

インターフェースは「変数やメソッドの定義忘れをコンパイラが解釈してエラー通知してくれる」という側面があると思いますが、JavaScriptではそのような実装はありません。

WikipediaのBuilderパターン にinterface / implements が例示されていましたので、javascript で示してみました。

codepen

  • JapaneseHouseBuilder は単一継承で無理やりインターフェースを実装
    (JavaScriptの成果物としては冗長になる)
  • KamakuraBuilder は 抽象化の定義のみ

インターフェースを実装しようとすると、コード量が増えるため minify が推奨されるブラウザ環境では無駄になります。が、設計図書等には、必須な変数、メソッドであることを示せばいいと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る