在一个子类中使变量成为 final 和 static,而在 Java 中的其他子类中保持变量不变

Making a variable final and static in one subclass, while keeping it variable in others in Java

我有一个超类和两个扩展它的子类。我想初始化一个名为 radius 的变量,它可以在子类 A 中自由设置,但对于子类 B 总是相同的。我可以在每次创建对象 B 时初始化该变量,但我想知道是否可以子类 B 中的变量 final 和 static,同时仍然能够在我的超类中实现 getter。我可能会实现更多的子类,这些子类的半径要么是最终的,要么是可变的。如果不是,我想知道什么是解决我的问题的最优雅的解决方案。这是一些可以工作但不是很好的示例代码。

abstract class SuperClass {

    public double getRadius() {
        return this.radius;
    }

    protected double radius;
}

class A extends SuperClass{

    public void setRadius(double radius) { // Would like to put this setter in SuperClass for future subclasses.
        this.radius = radius;
    }
}

class B extends SuperClass{
    public B() {
        radius = 0.2; //Want to make this static and final only for this subclass.
    }
}

Making a variable final and static in one subclass, while keeping it variable in others in Java

从技术上讲,你做不到。 一个字段要么是静态字段要么是实例字段,不能两者都是。
作为替代方案,覆盖 B class 中的 getRadius() 以提供不同的值:

@Override
public double getRadius() {
    return 0.2;
}

为了使这个常量得到尊重,您还应该覆盖 B class:

中的 setter
@Override
public void setRadius(double radius) {   
   throw new UnsupportedOperationException();
}

你为什么不试试这个:

在超类中将变量设为私有。 在超类中有一个 getter 和 setter 方法。

覆盖子类中的 setter 方法,这样就不可能更改变量。

像那样:

abstract class SuperClass {

    private double radius;

    public double getRadius() {
        return this.radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }
}

class A extends SuperClass{

}

class B extends SuperClass{
    public B() {
        super.setRadius(0.2d);
    }

    @Override
    public void setRadius(double radius) {
        throw new UnsupportedOperationException("My Info Text");
    }
}

另一种方法是将基础 class 放在自己的包 中,并使用受保护的 setter:

package sandbox.radius.base;

public class Radius {
    private double radius;

    public double getRadius() {
        return radius;
    }

    protected void setRadius(double radius) {
        this.radius = radius;
    }
}

然后在不同的包中实现,仅在适当的地方公开setter,委托给超级:

package sandbox.radius;

import sandbox.radius.base.Radius;

public class FixedRadius extends Radius {

    public FixedRadius() {
        setRadius(0.2);
    }

}

package sandbox.radius;

import sandbox.radius.base.Radius;

public class MutableRadius extends Radius {

    public void setRadius(double radius) {
        super.setRadius(radius);
    }

}

所以 API 更干净:

public class RadiusApp {

    public static void main(String[] args) {

        FixedRadius fr = new FixedRadius();
        fr.getRadius();
        // fr.setRadius(1.0); //compile error

        MutableRadius mr = new MutableRadius();
        mr.getRadius();
        mr.setRadius(1.0);
    }

}