Java抽象和接口

时间:2016-06-10 13:07:23

标签: java interface static abstraction

自从我弄乱了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"

现在我显然做错了什么,四处寻找并没有帮助。我非常肯定这是可能的,除非我对另一种语言感到困惑。

有人可以指出我正确的方向吗?感谢。

6 个答案:

答案 0 :(得分:4)

你在类B上调用了getName方法.B没有一个名为getName的静态方法,因此它在超类A中查找它。

也许您希望B的版本名称覆盖A?变量不会被覆盖。 A正在访问在A上定义的静态变量名,该方法最初在B上调用不会影响它。

继承和静态方法不能很好地协同工作。像多态这样的OO概念依赖于运行时调度,单词static应该意味着与之相反。使用多态性,程序在高级抽象中工作,通过超类型引用对象并让子类计算出细节。使用静态方法,您必须引用您希望调用该方法的特定子类,因此您没有这种抽象级别。

答案 1 :(得分:2)

再次欢迎回到Java。 您在A类和B类中使用静态变量。这些变量与类而不是对象相关联。

如果您更改方法以从用户获取名称,它将按预期工作。

答案 2 :(得分:0)

您需要覆盖方法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);
    }

}

答案 3 :(得分:0)

您面临的问题在于方法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关键字,您可以访问扩展类中的字段。

另见:

答案 4 :(得分:0)

班上有几点需要注意:

  1. 名称和描述是A和B中的静态变量
  2. getName是A
  3. 中的静态方法

    静态变量绑定到类,静态方法不能被重写

答案 5 :(得分:0)

这是预期的行为,因为类A的getName()方法可以访问它自己的类的成员变量,它是类A的“名称”。由于名称是不 > static 即使您将其设置为非静态并且您访问它,如下面的代码段所示,它将返回“None”。请记住,只有方法被覆盖而不是成员变量。因此,B类的“名称”不会覆盖“A”类的“名称”。

auto confirmOperation = [](auto pr) ->
    std::enable_if_t<std::is_same<decltype(pr.second), bool>::value> {
  assert(pr.second);
};

另外,如果要将“B”作为输出,请覆盖B类中A类的getName()方法,并使方法和变量非静态。