如何使用实例化变量对接口变量进行阴影处理



我在用实例化变量隐藏接口变量时遇到了一些问题。我知道如何通过重写方法并在方法中手动分配变量来实现这一点,但不知道如何使用调用该方法的任何对象的实例化变量。

public interface ShakesHands {
static final String name = "Gabe";
public void shakeHands (ShakesHands other);
}
class Student implements ShakesHands{
String name;
@Override
public void shakeHands(ShakesHands other) {
String othersName = other.name;
System.out.println(name + " shook " + othersName + "'s hand.");
}
}
class Parent implements ShakesHands{
String name;
@Override
public void shakeHands(ShakesHands other) {
String othersName = other.name;
System.out.println(name + " shook " + othersName + "'s hand.");
}
}
public class App {
public static void main(String[] args) {
Student student1 = new Student();
student1.name = "Bob";
Parent parent1 = new Parent();
parent1.name = "Sally";
student1.shakeHands(parent1);
}
}

这段代码将输出"Bob摇了Gabe的手"。有没有什么方法可以阻止它引用接口名称"Gabe",而是引用实例名称"Sally",这样我就得到了"Bob摇Sally的手"?

抛开编码风格和干净代码的问题不谈,以下是为什么你的代码总是打印"…握了Gabe的手":

握手的方法实现引用了ShakesHands实例中的"name",而不是实现类中的一个。由于ShakesHands中唯一的"name"在这里是"in scope",因此您最终总是使用值为"Gabe"的静态变量。

实际上,编译器最好始终使用静态变量值,而不是使用实现类的变量(如果存在此类变量)。派生类或实现类中的数据类型不需要与超类/接口中的相同,因此您可以将ShakeHand的名称设置为与Student的名称不同的类型。

示例:

public interface ShakesHands {
String name = "Gabe";
public void shakeHands(ShakesHands other);
}
class Student implements ShakesHands {
Integer name = Integer.valueOf(0);
@Override
public void shakeHands(ShakesHands other) {
System.out.println(name.getClass().getSimpleName() + " (in this class) with value "+name+" vs. " + other.name.getClass().getSimpleName()+" (in other class) with value "+other.name);
}
}

对于我的示例调用,printet文本是"值为7的Integer(在这个类中)与值为Gabe的String(在其他类中)"。

另一件事是:即使在程序的所有实现中,实现类中都有一个"name"变量:在编译时,编译器不知道运行时是否仍然如此。您的JAR可能在另一个定义了"UnnamedShakesHand"类(没有"name"变量)的程序中使用。那该怎么办?如果实现类用另一个类定义了"name",那么代码应该发生什么?它是否应该因为您的"StringothersName=other.name;"指令而引发"ClassCastException"?

长话短说:在"ShakesHands"接口中引入一个"StringgetName()"方法每个实现类都可以返回其名称的变量值,一切都很好。

最新更新