java中的最终字段继承

发布于 2024-12-10 20:36:35 字数 78 浏览 0 评论 0原文

是否可以让给定的子类初始化其超类中的静态最终字段?本质上,我希望子类配置所需的类范围变量。不幸的是,abstract关键字并不完全适用于字段。

Is it possible to have a given subclass initialize static final fields in its superclass? Essentially I would like for the subclass to configure required class-wide variables. Unfortunately, the abstract keyword doesn't exactly work with fields..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

飘然心甜 2024-12-17 20:36:35

不 - 如果有两个子类试图做同样的事情,你会期望它如何工作?如果您有静态最终字段,则它们必须由声明它们的类初始化。

如果您尝试同时使用静态字段和继承,那么老实说,这通常是一个错误的迹象 - 它们是两个概念,通常不能很好地结合在一起。人们经常尝试使用静态方法等来“伪造”继承,并且通常会以糟糕的方式结束 - 这听起来像是该主题的变体。

如果您能描述一下您的更广泛的情况,我们也许能够为您提供更多帮助。顺便说一句,为了可测试性,我强烈建议您一般避免使用静态。它们对于真正的常量来说很好,但是如果它是类似配置的东西,那么在构造对象时传递相关设置会更好(IMO)。

编辑:我可以看到四个选项可以更好地模拟您的情况:

  1. 使用注释:请参阅 True Soft 的答案
  2. maxHealth 设为方法,这样您就可以询问任何玩家的最大生命值是多少 中分别重写
  3. 是 - 这是多态的,因此可以在每个类

    Model PlayerPlayerClass

    公共类玩家{
        私有最终 PlayerClass 玩家类;
        私人健康; // ETC
    }
    
    公共类玩家类{
        私有最终 int maxHealth; //ETC
    }
    

    这样,您可以在“玩家类”级别继承,但您不必这样做 - 您可以创建多个 PlayerClass 实例,其行为 以同样的方式,但具有不同的统计数据...或者您可以子类化 PlayerClass 以提供自定义行为。那时,您可能根本不需要 Player 的不同子类。

  4. 与想法 3 相同,但使用枚举:

    public enum PlayerClass {
        精灵(10)、矮人(9)、人类(5);
    
        私有最终 int maxHealth;
        私人玩家类(int maxHealth){
            this.maxHealth = maxHealth;
        }
    }
    

我怀疑,就我个人而言,我的偏好将是最终选择。您仍然可以覆盖行为,但是您有一组固定的可能类 - 这可能相当准确地对您的游戏进行建模。

No - how would you expect it to work if there were two subclasses which tried to do the same thing? If you've got static final fields, they must be initialized by the class which declares them.

If you're trying to use static fields and inheritance together, that's usually a sign that something's wrong to start with, to be honest - they're two concepts which generally don't play well together. People often try to "fake" inheritance with static methods etc, and it usually ends badly - this sounds like a variation on that theme.

If you can describe your broader picture, we may be able to help you more. I would urge you to avoid statics in general for the sake of testability, by the way. They're fine for genuine constants, but if it's anything like configuration, it's nicer to pass in relevant settings when constructing an object (IMO).

EDIT: I can see four options which would model your situation better:

  1. Use annotations: see True Soft's answer
  2. Make maxHealth a method, so you can ask any player what their maximum health is - that's then polymorphic, so can be overridden in each class
  3. Model Player and PlayerClass separately:

    public class Player {
        private final PlayerClass playerClass;
        private int health; // etc
    }
    
    public class PlayerClass {
        private final int maxHealth; //etc
    }
    

    That way you can have inheritance at the "player class" level, but you don't have to - you could create several PlayerClass instances which behave the same way, but have different stats... or you could subclass PlayerClass to give custom behaviour. At that point you may not need different subclasses of Player at all.

  4. The same as idea 3, but using an enum:

    public enum PlayerClass {
        ELF(10), DWARF(9), HUMAN(5);
    
        private final int maxHealth;
        private PlayerClass(int maxHealth) {
            this.maxHealth = maxHealth;
        }
    }
    

Personally my preference would be the final option, I suspect. You can still override behaviour, but you have a fixed set of possible classes - which probably models your game reasonably accurately.

念﹏祤嫣 2024-12-17 20:36:35

关于 Jon Skeet 的回答,我认为“如果您尝试同时使用静态字段和继承”,这并没有那么糟糕。我建议你使用注释:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface AValue {
    /**
     * @return something final that is "static" (attached to a class), 
     * but also "abstract" (looks that it be changed in the subclasses)
     */
    String value();
}

@AValue("A default value") // you can ommit this, but all subclasses should add the annotation (so the method from Utils work OK)
abstract class A { }

@AValue("Value for class B")
class B extends A { }

@AValue("Value for class C")
class C extends A { }

class Utils {
    static String getValueOfClass(Class<? extends A> clazz) {
        return clazz.getAnnotation(AValue.class).value();
    }
}

Regarding Jon Skeet's answer, I don't think it's that bad "If you're trying to use static fields and inheritance together". I suggest you to use annotations:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface AValue {
    /**
     * @return something final that is "static" (attached to a class), 
     * but also "abstract" (looks that it be changed in the subclasses)
     */
    String value();
}

@AValue("A default value") // you can ommit this, but all subclasses should add the annotation (so the method from Utils work OK)
abstract class A { }

@AValue("Value for class B")
class B extends A { }

@AValue("Value for class C")
class C extends A { }

class Utils {
    static String getValueOfClass(Class<? extends A> clazz) {
        return clazz.getAnnotation(AValue.class).value();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文