Java 中的阴影

10 Sept 2024 | 4 分钟阅读

影射 (Shadowing) 是面向对象编程范式中的一个概念。它在不覆盖基类成员的情况下为其提供新的实现。影射和隐藏是相同的概念,但用于不同的上下文。它们是编译时过程。在本节中,我们将通过示例讨论 Java 中的变量和方法影射的概念。

OOP 中的影射是什么?

影射是一种计算机编程现象,其中在某个作用域(如决策块、方法或内部类)中声明的变量与包围作用域的另一个声明具有相同的名称。在这种情况下,该声明会影射包围作用域的声明。

简单来说,基类成员的原始实现会被派生类中提供的基类成员的新实现所影射(隐藏)。影射实际上是隐藏派生类中被覆盖的方法实现,并通过派生类对象调用父类的实现。

另外,请注意,被影射的元素无法通过名称单独引用,而是当代码使用元素名称时,编译器会将其解析为影射的元素。我们无法仅凭名称引用被影射的声明。这个概念就像掩码,所以它也被称为名称掩码 (name masking)

变量影射与变量隐藏

Java 允许我们声明三种类型的变量

  • 局部变量
  • 实例变量
  • 类变量

如果实例变量和局部变量具有相同的名称,并且我们想打印实例变量,在这种情况下,它将打印局部变量而不是实例变量。

当我们打印在方法中声明的变量时,将会在控制台上打印局部值。因此,我们可以说局部变量影射了实例变量。

让我们通过一个 Java 程序来理解影射的概念。

在下面的程序中,我们定义了两个变量,即 name 和 age,它们也在 display() 方法中定义。在类声明之后定义的变量称为实例变量,在方法内部声明的变量称为局部变量。

Shadowing.java

输出

Car Name: Bugatti
Price: 43000000

如果也想在方法中访问实例变量怎么办?我们可以使用 this 关键字来访问实例变量。考虑以下程序。

Shadowing.java

输出

Car Name: Bugatti
Price: 43000000
Car Name: Ferrari
Price: 50000000

让我们看另一个 Java 程序,用于相同目的。

Shadow.java

输出

x = 12
this.x = 1
Shadow.this.x = 0

方法影射

方法影射的概念与方法覆盖的概念相同。实例方法在超类和子类中都有定义。当我们调用子类的方法时,超类的方法会被子类覆盖。这个概念称为方法影射

MethodShdowing.java

输出

display() method of the subclass invoked.

请注意,静态方法不能被实例方法影射,因为它会导致歧义。但是,静态变量可以被实例变量影射(仅适用于子类)。考虑以下代码片段。

结论

OOP 中的影射和隐藏是描述同一事物的两个不同词语,但上下文不同。

隐藏与多态性相关,而影射则不然。当我们谈论隐藏时,意味着我们在讨论继承,其中派生类方法隐藏了来自正常继承方法调用链的基类方法。

另一方面,当我们谈论影射时,意味着我们在谈论作用域(如决策块、方法或内部类)。有时隐藏也被称为影射。