3

假设我有一个类Animal,然后是一堆扩展的子类Animal。假设我想要一个名为的公共字段name,它也应该存在于每个子类中。在每个子类中包含和初始化该字段的正确方法是什么?

1)将父类中的字段声明为protected,然后在每个子类中对其进行初始化。如果我这样做,将字段称为super.variable或简单地引用是否合适variable?就我个人而言,使用 super 更明显地表明该字段是在父级中声明的。(这是我目前正在做的)

2) 将父级中的字段声明为private,然后创建getterssetters访问该字段

3) 只需在每个子类中声明和初始化相同的变量

4)我缺少的另一种方法?

谢谢您的帮助。我知道这个问题是相当基本的,但我很好奇最合适的风格是什么。

编辑:

我不确定你们是否会看到这个,但这是一个后续问题。

有什么好的方法可以确保子类初始化字段吗?

4

5 回答 5

4

答案取决于您是否需要控制对该字段的访问以确保正确性(例如,确保同时更新某些其他字段)。如果子类可以直接旋转字段,那么只需使用protected. 如果您需要在设置字段时执行额外的检查或操作,您应该将其private设置为超类并让子类使用 setter 以确保您的逻辑运行。如果您知道始终需要该字段,则不应复制该字段;如果您不确定,那么您应该考虑使用 aninterface Animal并将字段放在AbstractAnimal implements Animal.

super在 Java 中,除了调用超类的方法版本之外,您不会使用任何东西。直接访问protected字段;这就是它们的用途,如果您需要知道,您的开发环境将跟踪它们的声明位置。

于 2013-08-02T00:23:52.927 回答
2

我投票给2:

创建一个私有字段,并拥有 setter 和 getter(可以对其进行保护以使它们只能被子类访问)。

如果您不需要 setter(只是一个 getter),则其他选项:

4)抽象getter并留给子类如何实现它

5) private final 字段,由抽象类构造函数和 getter 设置。

于 2013-08-02T00:22:26.680 回答
2

我总是制作字段protected字段,因为这有助于可调试性和可扩展性,并将公共 getter 和 setter 放在它们上以创建“属性”。

(在尝试进行相当合法的调试/扩展工程时,各种开源库、Swing 组件等中的私有字段一再成为我的障碍。所以我相当反对它们。)

如果我担心可追溯性,其中可能涉及行为或错误(例如获取和缓存的值),我可能会通过 getter 访问子类中的变量。

我在写入this.name变量时总是使用它——它可以很好地提高代码清晰度,并且它简化了 setter 中的参数命名。(仅用于参数 &字段。)namethis.name

我在读取this变量时不使用- 这是我想要明确的写入。对于集合,我使用 List 或 map 或任何其他字段作为后缀,即 childList ——但参数和本地变量是“子项”。

super我在提到变量时从不使用。Super 只对消除具有相同名称的继承和声明变量的歧义有意义,您可以合法地这样做 - 但几乎可以保证代码风格、清晰度和容易导致错误。


我还喜欢使大多数属性可变——而不是仅在构造时可设置。如果您想使用 Hibernate 或持久化数据,这将很有帮助。过度依赖构造函数初始化往往会演变成困难——大而脆弱的调用签名、无法将类用于部分形成的数据或“特殊值”答案,以及初始化顺序问题。

于 2013-08-02T00:22:28.377 回答
2

我认为这取决于情况。如果名称字段应该可以公开访问,我会将该字段声明为私有,然后创建公共的 get/set 方法。有时您希望将基类上的字段作为派生类的公共接口的一部分公开。

如果名称字段只能在派生类中使用,我只会使用受保护的字段。

如果要确保子类初始化字段,请在基类构造函数中添加参数,然后使用派生类构造函数提供的参数初始化基类中的字段。

于 2013-08-02T00:23:41.473 回答
1

我通常使用选项 2(私有 + 访问器 - 受保护,不需要公共)有机会自定义变量访问。

关于您的编辑:如果是强制性要求,则强制输入构造函数名称

Animal(String name) {
    this.name = name;
}

或者

String getName()  {
    if(null == name){
        name = initializeName();
    }
    return name;
}

initializeName()抽象

于 2013-08-02T00:30:00.650 回答