当一个父类和它的子类有相同名称的域时,此时可被称为变量阴影。如果父类的域有私有变量或者在其他的封装中,那么没有什么争议而言,因为子类不能访问父类的私有参数。
然而,如果父类中的名称变量可以被子类的实例访问,此时一些非直觉的规则决定父类的哪些域被访问,这些规则的选择取决于在调用变量的类。
例如,表A包含两个类,Base and Sub,这两个类为父类和子类的关系。这两个类都有一个名为field的整数域。表B显示了类Sub的实例。
以access one为标记的第一种表达式可以通过名为s的Sub实例中的field变量来访问,这一访问正如很多人所期待的,它可以返回数值1。第二种表达式以Access two为标记,显示的是变量阴影中的逻辑连接。即使表达式b==s返回true,第二种访问的b.field结果为0。
先抛开b和 s之间的联系,b.field和s.field的区别可以很清楚地说明了变量阴影中存在的陷阱。范例中b和 s之间的差别在于它们的存储变量的类型。变量阴影并非全尽然的要定义的数据类型,但是开发人员却出奇地常常犯这样的错误。
以access three和 access four为标记的表达式遵循类型数据匹配的规则。access three返回了数值1。同样的,access four返回了数值0。
虽然子类中的名称域掩盖了父类中的同名物,不同的术语采用了不同的方法来讨论了这些相似的问题。子类中的方法可以访问父类的方法。在表A中,你可以看到Sub 类中的getField方法与Base类中的getField方法有相同的名称和参数。
表C显示与表B中相同的对象实例,然而结果却不尽然相同,表C更类似于面向对象设计的结果。
过于重视方法和变量阴影之间的差别在于当比较表C和表B中的access two时,前者是可见的。表B中的父类中的域可以被访问,但是表C中的子类的变量却可以被调用。
严格遵循实例/引用类型是多态性的核心。多态性是一个很重要的特性,它代表着类的对象的行为,是面向对象程序设计的基本概念。多态性是基于方法的特性。
继续以上的范例,可以看到表C中的access three和 access four。与access one和 access two一样,这两个表达式的输出都为1。这也是由于多态性的原因,为了能够通过调用方法来访问Base类的阴影变量,必须使用Sub类中的syntaxsuper.field。
客观上说,无论是变量阴影,还是过于重视方法,都是相当复杂的,它们常常被反对使用。但是二者又是合法的Java代码,多态性和变量阴影等方法都显示了开发人员超乎平凡的编程技能,虽然这些方法都潜伏着错误的陷阱。