【问题标题】:Access property/constant in extended classes访问扩展类中的属性/常量
【发布时间】:2019-02-18 09:24:12
【问题描述】:

我正在努力实现以下目标:

我有一个父类,有一些逻辑。在子类中,我“重新定义”常量/属性。有没有办法让父类中定义的方法可以访问子属性?或者更具体地说 - 在下面的示例中,有没有办法强制“out”方法编写 extended 而不是 base

public class BaseTest {
    public static final String x = "base";

    public void out() {
        System.out.println(x);
    }
}

public class ExtendedTest extends BaseTest{
    public static final String x = "extended";
}

public class Main {
    public static void main(String[] args) {
        BaseTest base = new BaseTest();
        ExtendedTest extended = new ExtendedTest();
        base.out(); // base (as expected)
        extended.out(); // base (extended expected)
        System.out.println(extended.x); // extended (as expected)
    }
}

我主要来自 PHP 世界,这种方法工作得很好。不知道我是否遗漏了什么,或者 Java 的设计本身不允许这样做。

谢谢。

注意:无论属性是否为静态,这不重要。我只是希望能够覆盖子类中的任何类型的属性(就像我可以覆盖一个方法一样),根据我迄今为止收到的答案,这在 Java 中似乎是不可能的。在 PHP 中这是绝对可能的,这就是我问这个问题的原因。

【问题讨论】:

  • 为什么那是一个静态字段呢?解决这个问题的最天真的方法是一个本地字段(不是静态的)和一个返回该字段值的抽象方法。
  • 顺便说一句,您应该遵守 Java 命名约定:常量(static final 变量)应该在 UPPER_SNAKE_CASE 中。
  • Malis,术语在这里非常重要:在 Java 中,属性由 getter 和/或 setter 方法定义,而不是由 field(成员变量);某些属性甚至没有后备字段,而是在需要时进行计算。字段访问(无论是静态的还是实例的)在编译时解析,因此直接字段引用不受重新声明另一个同名字段的影响。在 Java 中为此使用了方法,句号。

标签: java inheritance


【解决方案1】:

static 字段不受继承。 out() 方法主体中的x 引用BaseTest.x。由于您没有覆盖out(),因此out() 方法的主体仍会打印BaseTest.x 的值。

【讨论】:

  • 就像上面提到的,它不是静态与否,而是在父/子中定义。换句话说,是否可以在父类中创建基本逻辑并将其反映在子类中实现的更改?
【解决方案2】:

静态成员在编译时解析,添加ExtendedTest.x 不会影响同样存在的BaseTest.x,这是BaseTest#out() 方法所链接的内容。

要完成你想要的,你需要一个重写的方法:

public class BaseTest {
    public String x() {
        return "base";
    }

    public final void out() {
        System.out.println(x());
    }
}

public class ExtendedTest extends BaseTest {
    @Override
    public String x() {
        return "extended";
    }
}

此模式通常与基类或接口中的抽象方法一起使用,以要求子类定义属性,例如名称或键。

【讨论】:

  • 这正是我想要避免的。但只要似乎无法使用我的“PHP 方法”,我就必须在没有它的情况下过上自己的生活 :) 无论如何,谢谢你的澄清。
  • @Malis 如果您可以更详细地解释您实际尝试执行的任务,我们或许可以帮助展示更惯用的 Java。一般来说,属性只是透明地继承自超类 (BaseTest#getX()),如果需要更改属性的值,则使用 setter 进行更改。
  • 嗯,cmets 有点短,但我会试试。假设我有一个基类 Vehicle 和扩展类 Car。车辆有一个“功能”轮子(这可能是一个普通属性,但在 PHP 中通常是一个常量;并且常量在 Java 中不存在,因此静态最终......)在 PHP 中,基类可以通过以下方式访问“共享”常量static::WHEELS 和子类只包含 class Car extends Vehicle { const WHEELS = 4; } 它不需要特殊的构造函数,没有重写方法,只需一行,整个逻辑都在基类中。我在 Java 中寻找类似的行为。
  • @Malis 您可以覆盖方法或定义属性wheels 并在Car 构造函数中设置其值。
猜你喜欢
  • 1970-01-01
  • 2016-12-06
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
相关资源
最近更新 更多