砸Java抽象和/或接口了,但是我现在回到它进行一个项目,有些事情让我紧张起来。下面是我的代码片段。
public class A {
private static String name = "None";
private static String description = "No description";
public A() {}
public A(User user) {
user.setData(this);
}
public static String getName() {
return name;
}
public static String getDescription() {
return description;
}
}
public class B extends A {
private static String name = "B";
private static String description = "This is B";
public B() {}
public B(User user) {
super(user);
}
}
public class User {
private A a;
public void setData(A a) {
this.a = a;
}
public A getData() {
return a;
}
}
当我使用B.getName()
时,我希望它返回"B"
但它返回"None"
。
现在我显然做错了什么,四处搜索并没有一点帮助。我相当肯定这在某种程度上是可能的,除非我与另一种语言混淆。
有人可以指出我正确的方向吗?谢谢。
B 没有一个名为 getName 的静态方法,因此它在超类 A 中查找它。
也许你希望 B 版本的名字覆盖 A 的名字?变量不会被覆盖。A 正在访问在 A 上定义的静态变量名称,该方法最初是在 B 上调用的,这不会影响这一点。
继承和静态方法不能很好地协同工作。像多态性这样的OO概念依赖于运行时调度,static
这个词应该意味着与此相反。通过多态性,程序在高度抽象中工作,通过超类型引用对象并让子类计算出细节。使用静态方法,您必须引用要调用方法的特定子类,因此您没有该级别的抽象。
欢迎再次回到 Java。您在类 A 和 B 中使用静态变量。这些变量与类而不是对象相关联。
如果您更改方法以从用户获取名称,它将按预期工作。
你需要覆盖方法getName():
public class B extends A {
private static String name = "B";
private static String description = "This is B";
public B() {}
@Override
public static String getName() {
return name;
}
public B(User user) {
super(user);
}
}
您面临的问题在于方法的定义 getName
和 getDescription
: 它们在类A
中定义为静态成员。这意味着即使在调用B.getName()
时,实际调用也是A.getName()
的,并且静态成员变量值name
设置为 None
。
在考虑继承时,您必须小心您声明为静态的内容。这与接口或抽象类无关。
public class A {
protected String name = "None";
protected String description = "No description";
public A() {}
public A(User user) {
user.setData(this);
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
}
public class B extends A {
public B() {
name = "B";
description = "This is B"
}
public B(User user) {
super(user);
}
}
public class User {
private A a;
public void setData(A a) {
this.a = a;
}
public A getData() {
return a;
}
}
使用 protected
关键字,您可以访问扩展类中的字段。
另请参阅:
- http://www.javatpoint.com/static-keyword-in-java
- https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
在你的类中需要注意的几件事:
- 名称和描述是 A 和 B 中的静态变量
- getName 是 A 中的静态方法
变量绑定到类,静态方法不能被重写
预期的行为,因为类 A 的 getName() 方法可以访问其自己的类的成员变量,该成员变量是类 A 的"名称"。这不是因为名称是静态的,即使您将其设置为非静态并且您访问它,如下面的代码片段所示,它也会返回"None"。请记住,只有方法被覆盖,而不是成员变量。因此,B类的"名称"并不覆盖"A"类的"名称"。
B b = new B();
System.out.println(b.getName()); --> "None" ("name" is non-static)
----------------------------------------------
System.out.println(B.getName()); --> "None" ("name" is static)
另外,如果你想得到"B"作为输出,覆盖类 B 中类 A 的 getName() 方法,并使方法和变量非静态。