问题描述
我想我在开始之前就知道了这个问题的答案,但在 Google 上按照这些思路进行了多次搜索后,我找不到明确的答案。
这个问题假设我们在 Ecmascript 6 及更高版本中使用类模式。
我最初的信念是方法覆盖
在面向对象编程中,是一种语言特性,它允许 子类或子类来提供一个特定的实现 已由其超类或父类之一提供的方法 类。 Wikipedia
方法阴影(不仅仅是块范围的“变量阴影”- Wikipedia)另一方面似乎只在强类型语言(如 C#)的上下文中才有意义,它允许您设置一个实例一个“子类”作为“基类”类型,这意味着实例将恢复到基类方法而不是任何“隐藏”方法。
public abstract class BaseClass
{
public virtual void shadowedMethod()
{
Console.WriteLine("This is the BaseClass version");
}
}
public class DerivedClass : BaseClass
{
public new void shadowedMethod()
{
Console.WriteLine("This is the Derived child class");
}
}
public class Program
{
public static void Main()
{
BaseClass instance = new DerivedClass(); // Because BaseClass type is set instead of DerivedClass
instance.shadowedMethod(); // It prints "This is the BaseClass version"
}
}
Code adapted from this article
所以问题是:为什么大多数 JS 线程和文档ECMA Standard 交替使用覆盖和阴影(但倾向于支持阴影)?我们不应该只用一个术语来停止混淆吗?在 Javascript 中重写和隐藏方法之间实际上存在细微差别吗?
解决方法
我努力在 Javascript 的上下文中找到明确的定义。所以这是我回答自己问题的最佳尝试。
派生类(作为基类)中所有同名的方法似乎都是“影子方法”,接受相同参数(因此创建相同接口)的方法子集也是“覆盖的方法,因为“被覆盖的成员必须接受相同的数据类型和参数数量”。 (see this article)
派生类上的方法如果使用相同的签名(接受相同的参数)会覆盖父类/基类:
class BaseClass {
overriddenMethod(a) {
return a;
}
}
class DerivedClass {
overriddenMethod(a) {
return 2*a;
}
}
但如果派生类方法接受不同的参数,它只是“遮蔽”:
class BaseClass {
overriddenMethod(a) {
return a;
}
}
class DerivedClass {
overriddenMethod(a,b) { // This is not overriding because it accepts different parameters.
return a + b;
}
}
更详细地说,它是“阴影”,因为 Javascript 是一种原型语言,这意味着一切都是对象(甚至类定义),因此一切最终都是对象上的变量,因此“变量阴影”是对象上的变量原型链上的外部作用域。