2017-09-27 4 views
2

私はJavaのバックグラウンドから入ってくる間にJavascript(es6)でプログラミングしています。 Javaでは、私はインターフェイス/抽象クラスをよく作成しますが、この機能はes6にはありません。一般に、ストラテジーパターンなどのデザインパターンを使用するために抽象メソッドを書くのが好きです。私は他の人が抽象クラスの独自のバージョンを実装しようとしているのを見ましたが、特に好きではありません。Javascript(es6)のOOP言語の抽象メソッドの動作を実現する最善の方法は何ですか?

Animalという抽象クラスがあり、抽象メソッドcryがあるとします。私が見てきた何より、Javascriptのコードは次のようになります。

class Animal { 
    constructor() { 
    if (new.target === Animal) { 
    throw new TypeError("Cannot construct Animal instances directly"); 
    } 
    } 

    cry() { 
    throw new Error('You have to implement the method cry!'); 
    } 
} 

とのはCatDogAnimalのサブクラスであるとしましょう。次に、それらの実装次のようになります。私はこのコードについては好きではありません

class Cat extends Animal { 
    cry() { 
    return 'meow'; 
    } 
} 

class Dog extends Animal { 
    cry() { 
    return 'woof'; 
    } 
} 

何があなたがクラスは抽象クラスであることを示すために例外文を書かなければならないということです。

しかし、私は、コールバックとファクトリメソッドを使用する方が良いアプローチだと思います。抽象クラスに抽象メソッドを持たせるのではなく、抽象クラスにコールバック関数を渡し、これを想定した抽象メソッドとして使用することができます。 Animal例は、以下のものに変更することができます。

class Animal { 
    constructor(cryCallback) { 
    this.cryCallback = cryCallback; 
    } 

    cry() { 
    return this.cryCallback(); 
    } 
} 

CatDogオブジェクトのインスタンスを作成するためには、基本的にファクトリメソッドでそれらを作成することができます。それは次のようになります。

function createCat() { 
    return new Animal(() => 'meow'); 
} 

function createDog() { 
    return new Animal(() => 'woof'); 
} 

あなたがCatインスタンスを作成し、cryを呼び出した場合、それは次のようになります。

console.log(createCat().cry()); //meow 

このアプローチを使用することの利点は、あなたが実際にはないことですcryを実装する必要があるため、Animalのインスタンスを呼び出します。次に、CatオブジェクトまたはDogオブジェクトの作成をファクトリメソッドで隠すことができます。

このアプローチについてどう思いますか教えてください。 Javascriptで抽象メソッドを実現するためのより良いアプローチはありますか?

+2

使用typeecriptが、それはあなたがしているもののためにシンタックスシュガーを提供します。あなたは、(コードが正しいかどうかはチェックしませんでした)このような何かを行うことによって、これらの2の混合を行うことができを参照してください。Typescriptは、コンパイル時にオプションの型チェックを提供します – Dummy

答えて

0

例外を投げる最初のオプションは、IMOです。

私が考える第一の理由は次のとおりです。

function createCat() { 
    return new Animal(() => 'meow'); 
} 

createCat() instanceof Cat // This line is pointless, cat does not even exist. 

しかし、あなたが使用している場合:

class Cat extends Animal { 
    cry() { 
    return 'meow'; 
    } 
} 

new Cat() instanceof Cat // true 
new Cat() instanceof Animal // true 

あなたは、元を使って、持っていない機能を持っています。

編集:

function factoryAnimal(ctror) { 
    const r =() => { 
    ctor.prototype = Object.create(Animal); 
    const res = new Animal(ctror); 
    res.__proto__ = ctror.prototype; 
    return res; 
    } 
    return r; 
} 

function Cat() { 
    return "meow"; 
} 

const createCat = factoryAnimal(Cat); 

createCat() instanceof Cat // This should work returning true. 
+0

私は実際に 'instanceof'を使用するファンではありません。基本的には、Liskovの原則に違反しています。「プログラムモジュールがBaseクラスを使用している場合、プログラムモジュールの機能に影響を与えずに、Baseクラスへの参照をDerivedクラスに置き換えることができます。通常、 'instanceof'を使用している場合は、抽象クラスの2つのサブクラスが抽象クラスを置き換えることができなかったことを意味します。 – mtber75

+0

これは純粋なOOP言語に当てはまります。しかし、 'instanceof'はまだJavaScriptで非常に便利です。これは機能的なものとしてよく使われます。 – lilezek

関連する問題