Java 抽象和接口


我已经很久没有搞

砸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 方法,

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);
    }
}

您面临的问题在于方法的定义 getNamegetDescription : 它们在类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

在你的类中需要注意的几件事:

  1. 名称和描述是 A 和 B 中的静态变量
  2. 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() 方法,并使方法和变量非静态。

最新更新