在Javascript(es6)中实现OOP语言抽象方法行为的最佳方法是什么?
我是在Java背景下用Javascript(es6)编程的。在Java中,我通常编写接口/抽象类,而es6中缺少此功能。通常,我喜欢编写抽象方法以使用设计模式,例如策略模式。我见过其他人尝试实现他们自己版本的抽象类,但我并不特别喜欢它 假设我们有一个名为在Javascript(es6)中实现OOP语言抽象方法行为的最佳方法是什么?,javascript,oop,inheritance,Javascript,Oop,Inheritance,我是在Java背景下用Javascript(es6)编程的。在Java中,我通常编写接口/抽象类,而es6中缺少此功能。通常,我喜欢编写抽象方法以使用设计模式,例如策略模式。我见过其他人尝试实现他们自己版本的抽象类,但我并不特别喜欢它 假设我们有一个名为Animal的抽象类,它有一个抽象方法cry。据我所见,Javascript代码如下所示: class Animal { constructor() { if (new.target === Animal) { throw ne
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!');
}
}
让我们假设Cat
和Dog
是Animal
的子类。然后,它们的实现如下所示:
class Cat extends Animal {
cry() {
return 'meow';
}
}
class Dog extends Animal {
cry() {
return 'woof';
}
}
class Animal {
constructor(cryCallback) {
this.cryCallback = cryCallback;
}
cry() {
return this.cryCallback();
}
}
function createCat() {
return new Animal(() => 'meow');
}
function createDog() {
return new Animal(() => 'woof');
}
console.log(createCat().cry()); //meow
我不喜欢这段代码的地方在于,您必须编写异常语句来指示类是抽象类
然而,我认为有一种更好的方法使用回调和工厂方法。我们可以将回调函数传递到抽象类中,并将其用作假定的抽象方法,而不是为抽象类提供抽象方法。Animal
示例可以更改为以下内容:
class Cat extends Animal {
cry() {
return 'meow';
}
}
class Dog extends Animal {
cry() {
return 'woof';
}
}
class Animal {
constructor(cryCallback) {
this.cryCallback = cryCallback;
}
cry() {
return this.cryCallback();
}
}
function createCat() {
return new Animal(() => 'meow');
}
function createDog() {
return new Animal(() => 'woof');
}
console.log(createCat().cry()); //meow
为了创建Cat
和Dog
对象的实例,基本上可以使用工厂方法创建它们。它将如下所示:
class Cat extends Animal {
cry() {
return 'meow';
}
}
class Dog extends Animal {
cry() {
return 'woof';
}
}
class Animal {
constructor(cryCallback) {
this.cryCallback = cryCallback;
}
cry() {
return this.cryCallback();
}
}
function createCat() {
return new Animal(() => 'meow');
}
function createDog() {
return new Animal(() => 'woof');
}
console.log(createCat().cry()); //meow
如果创建一个Cat
实例并调用cry
,它将如下所示:
class Cat extends Animal {
cry() {
return 'meow';
}
}
class Dog extends Animal {
cry() {
return 'woof';
}
}
class Animal {
constructor(cryCallback) {
this.cryCallback = cryCallback;
}
cry() {
return this.cryCallback();
}
}
function createCat() {
return new Animal(() => 'meow');
}
function createDog() {
return new Animal(() => 'woof');
}
console.log(createCat().cry()); //meow
使用这种方法的优点是,您实际上并没有调用Animal
的实例,因为您被迫实现cry
。其次,您可以使用工厂方法隐藏创建Cat
或Dog
对象的实现
请让我知道你对这种方法的看法。有没有更好的方法来实现Javascript中的抽象方法?在我看来,引发异常的第一个选项要好得多 我想到的第一个原因是:
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
你有一个使用前者所没有的特性
编辑:您可以通过这样做混合使用这两种代码(我没有检查代码是否正确):
使用typecript,它为您所指的内容提供语法上的糖分。Typescript在编译时还提供可选的类型检查。实际上,我不太喜欢使用
instanceof
。基本上,它违反了Liskov的原则,即:“如果程序模块使用基类,那么对基类的引用可以替换为派生类,而不会影响程序模块的功能”。通常,如果您使用的是instanceof
,这意味着抽象类的两个子类不能替代抽象类。这对于纯OOP语言是正确的。然而,instanceof
在JavaScript中仍然非常有用,JavaScript通常用作函数式JavaScript。