如何防止特定方法的继承?

kam*_*o94 7 javascript inheritance ecmascript-6

假设我有两节课,A并且B. B扩展A并因此继承其所有方法。如果我愿意的话,我也可以覆盖它们。我的问题是我是否可以阻止B继承A. 到目前为止我所尝试的看起来像这样。

// setup
class A {
  constructor(x) {
    this.x = x;
  }

  valueOf() {
    return this.x;
  }

  toString() {
    return `{x:${this.x}}`;
  }
}

class B extends A {
  constructor(x) {
    super(x);
    delete this.valueOf;
  }
}

delete B.prototype.valueOf;

// example
const a = new A(42);
const b = new B(42);

// should work
console.log(a.valueOf());
// should throw TypeError, not a function
console.log(b.valueOf());
Run Code Online (Sandbox Code Playgroud)

Jef*_*f M 8

有几个人已经告诉您如何解决您的问题。现在我想尝试说服你不要这样做。;-)

继承应该模拟 IS-A 关系。或者,更具体地说,是 IS-SUBSTITUTABLE-FOR-A 关系。这就是里氏替换原则( SOLID中的“L” )。

任何期望对“A”对象进行操作的代码都应该能够被赋予“B”对象(“A”替换为“B”),并且一切都应该仍然可以正常工作。但是,如果“B”缺少一个方法,如果它不提供“A”的完整接口,那么它就不再是可替代的,而且很有可能这不是使用继承的正确情况。


Yur*_*nko 3

实际上valueOf这是一个坏例子,因为每个对象都从Object.prototype. 尝试console.log(({}).valueOf())

但你可以通过隐藏这个属性来解决这个问题

// setup
class A {
  constructor(x) {
    this.x = x;
  }

  valueOf() {
    return this.x;
  }

  toString() {
    return `{x:${this.x}}`;
  }
}

class B extends A {
   get valueOf() { return undefined }
}

class C extends A {
}

Object.defineProperty(C.prototype, 'valueOf', {})


// example
const a = new A(42);
const b = new B(42);
const c = new C(42);

// should work
console.log(a.valueOf());
// should throw TypeError, not a function
try {
  console.log(b.valueOf());
} catch (e) {
  console.log(e.message)
}



try {
  console.log(c.valueOf());
} catch (e) {
  console.log(e.message)
}
Run Code Online (Sandbox Code Playgroud)