JavaScript-我应该使用需要特定接口的继承模型



我有点困境。我正在使用ES6类来构建简单的类层次结构。一个带有方法的基类,3个子类覆盖该方法。在某个时候,我正在浏览我称之为此方法的实例列表。从技术上讲,如果我可以简单地保证我所有的对象(任何类型的对象(提供一个名称的方法,那么我不需要类层次结构。哪种方法更好?

class Base {
  constructor() {
  }
  method() {
    console.log('base')
  }
}
class Subclass1 extends Base{
  constructor() {
    super()
  }
  method() {
    console.log('sc1')
  }
}
class Subclass2 extends Base{
  constructor() {
    super()
  }
  method() {
    console.log('sc2')
  }
}
class Subclass3 extends Base {
  constructor() {
    super()
  }
  method() {
    console.log('sc3')
  }
}
classInstances = [new Subclass1(), new Subclass2(), new Subclass3()];
classInstances.forEach(instance => {
  instance.method();
})
// or using any kind of objects...
obj1 = {
  method() {
    console.log('obj1');
  }
}
obj2 = {
  method() {
    console.log('obj2');
  }
}
obj3 = {
  method() {
    console.log('obj3');
  }
}
objectInstances = [obj1, obj2, obj3];
objectInstances.forEach(instance => {
  instance.method();
})

是的,只需编程到接口。

您在任何地方都没有使用Base.prototype.method,这是毫无意义的 - 因此将其丢弃。然后Base只是一个空的类,几乎等同于Object,因此也毫无意义。您实际上在这里没有使用任何继承功能,您也不需要类层次结构。

x instanceof Base的测试是唯一剩下的用例,但是再次typeof x.method == "function"更容易,更灵活。

javaScript使用'原型继承',而不是其他面向对象的语言的经典继承。这是一种合理的方法来测试一个对象是否基于给定的原型,但是鉴于可以自由地"修补" JavaScript对象以覆盖原型,甚至突变原型,因此您需要谨慎对待对象的假设。

如果您期望给定的方法存在,那么它可能更可靠地针对该方法进行测试,但是有时在代码中读取不太好。

您会遇到的一个问题是创建定义类型但没有默认行为的"基础"类。例如,在这里,我们可以为AnimalSpeakable创建基本类型,但是speak方法将需要是一个no-op或丢弃错误的方法。当然,当您无法定义预期行为时,这在开发过程中可能很有用。

另外,JavaScript不允许多个继承,因此您不能像其他语言那样实现"接口",尽管您可以创建获得类似结果的复合原型。

class Thing {
  constructor(name) {
    this.name = name
  }
}
class Dog extends Thing {
  speak() {
    return 'woof';
  }
}
class Cat extends Thing {
  speak() {
    return 'meow';
  }
}
class House extends Thing {
}
const things = [new Dog('Rover'), new Cat('Tibbles'), new House('Foo Hall')];
things.forEach(thing => {
  if (typeof thing.speak === 'function') {
    console.log(`${thing.name} says '${thing.speak()}'`);
  } else {
    console.log(`${thing.name} cannot speak`);
  }
});

最新更新