Java - 在子类中初始化超类变量?

时间:2012-12-28 22:46:01

标签: java variables subclass superclass

好的,例如,假设我有一个名为“Vehicle”的抽象类。除了其他方面,Vehicle类还有一个名为wheels的静态变量,它没有被初始化。我想要做的是从Vehicle类扩展其他子类,如“Motorcycle”和“Truck”,并在这些子类中初始化轮子。

代码:

public abstract class Vehicle {
    static int wheels; //number of wheels on the vehicle
}

但下面的内容不起作用:

public class Motorcycle extends Vehicle {
    wheels = 2;
}

有没有办法有效地做到这一点?

编辑: 感谢所有回复的人。我认为制作实例可能是一种更好的方法,而不是将它们全部放在不同的类中,但我没有完全得到java的“静态”部分,所以我需要一些帮助。

我正在尝试为我的程序做的是为摩托车和卡车类提供单独的精灵,我希望它们是静态的,这样我每次创建一个实例时都不必重新加载图像摩托车或卡车。除此之外,它们将具有几乎相同的属性,这就是为什么它们都将从Vehicle超类扩展。

我可以看到这样做的唯一另一种方法是不在Vehicle类中声明sprite变量,而是在Motorcycle / Truck类中声明,如下所示:

public abstract class Vehicle {
//Other coding
}

public class Motorcycle extends Vehicle {
static BufferedImage sprite = //initialize image
//Other coding
}

public class Truck extends Vehicle {
static BufferedImage sprite = //initialize image
//Other coding
}

7 个答案:

答案 0 :(得分:12)

如果'车轮'是静止的,只有一个,它将同时适用于所有车辆。因此,三轮车,摩托车,18轮卡车和福特都将拥有相同数量的车轮。

这对我没有意义。最好让'wheels'成为父类中的实例变量,但每个子类都设置得恰当。

但你可以试试

Vehicle.wheels = 2;

注意:自从您添加到问题中后,我正在添加我的答案。

我喜欢你在每个子类中都有静态的想法。但你应该把它们变成私人的。然后将一个抽象方法放在父类(Vehicle)中,如

public abstract BufferedImage getSprite();

然后每个直接子类必须具有相同的方法,并且它可以返回私有静态变量。

使变量成为静态,因此您只需加载一次。将它们设为私有,以便类本身之外的代码不会愚弄它并引入错误。如果可能的话,你可以让它们成为'final',这样类中的代码就不能在事后改变它并引入bug。 (一个'最终'变量不能改变它的值,但它的值的内容可能会改变。所以'最终'并不是一个很好的例子。)

答案 1 :(得分:6)

你要做的事情从根本上是有缺陷的。您可以使Motorcycle初始化wheels一次:

// Static initializer
static
{
    wheels = 2;
}

...或每次创建实例时:

// Instance initializer
{
    wheels = 2;
}

但是只有一个变量 - 不是Motorcycle的一个,Truck的一个等等。如果你对Truck和{{Motorcycle做同样的事情1}},然后最后初始化的那个将“赢”。

目前还不清楚你想如何使用这个字段 - 但是如果你只有一个静态字段,那么它只会有一个值 - 而不是每个子类一个。

答案 2 :(得分:2)

静态成员只定义一次,并且对每个扩展类都是通用的。更改其中一个中的值将影响所有其他值。 这就是我认为你真正想要实现的目标:

public abstract class Vehicle {
    private int _wheels; //number of wheels on the vehicle
    public int getWheels(){return _wheels;}

    protected Vehicle(int wheels){
        _wheels = wheels;
    }
}

public class Motorcycle extends Vehicle {
    public Motorcycle(){
        super(2);
    }
}

public class Car extends Vehicle {
    public Car(){
        super(4);
    }
}

答案 3 :(得分:2)

我认为这是一种更优雅的方式

我要提议的内容仍然受到您需要实例的限制。我没有看到任何方法,因为您希望wheels作为超类的一部分公开,但wheels的值取决于Vehicle的子类和内部没有实例的子类类型没有概念。

在我看来,' wheel'在这种情况下既不是静态也不是非静态属性。它是 元数据 类。指定类元数据的Java方法是通过注释。

您需要的是用户定义的注释,如下所示:

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface VehicleMetadata{
    int wheels();
}

然后按如下方式注释Motorcyle:

@VehicleMetadata(2)
public class Motorcycle extends Vehicle {}

在超类中,您提供了一个获取注释属性值的访问器。我建议您使用"懒惰的评估" 方法,这样每次需要时都不会使用反射。

请注意使用this获取实例:

private String wheelsValue;

public String getWheels() {
    if (this.wheelsValue== null) {

        VehicleMetadatane = null;
        for (Annotation annotation : this.getClass().getAnnotations()) {
            if (annotation instanceof VehicleMetadata) {
                ne = (VehicleMetadata) annotation;
                break;
            }
        }

        wheelsValue = ne.wheels();
    }
    return wheelsValue ;
}

在我看来,这是最优雅的解决方案。

答案 4 :(得分:2)

原始类声明:

public abstract class Vehicle {
    static int wheels; //number of wheels on the vehicle
}

public class Motorcycle extends Vehicle{...}
public class Truck extends Vehicle{...}

不起作用,因为静态变量与声明它的类一起使用。静态类变量仅为每个类的一个变量实例创建内存存储,而不是每个类对象。当编译器(jvm)在类Vehicle中看到静态变量时,它会将内存分配给该变量,并且该内存位置是静态的(不会更改)。 Vehicle类的每次后续使用,无论是扩展还是实例化为对象,都将指向静态变量的内存中的相同位置。

为了在子类中使用静态变量,您必须在方法中使用它。所以,你本质上可以像这样重写你的摩托车类:

class Motorcycle extends Vehicle{
    public Motorcycle(){
        wheels = 2;
    }
}

它会编译;但是,您可能无法获得预期的结果。例如,如果你在你的代码中执行此操作(假设Truck类被声明为类似于Motorcycle类并且为轮子分配4并且有一个getter方法来返回轮子的值)。

Motorcycle cycle = new Motorcycle();
Truck pickup = new Truck();
...
System.out.println("Motorcycle has " + cycle.getWheels() + " wheels.");

将打印:

摩托车有4个轮子。

答案 5 :(得分:0)

也许你想考虑一下你正在使用的构造函数。

public Vehicle(int wheels) {
    this.wheels = wheels; 
}

public Motorcycle(int wheels) {
    super(wheels);
}

public Motorcycle cycle = new Motorcycle(2);

摩托车使用知道如何处理参数的超级构造函数。它会自动将轮子设置为2。

答案 6 :(得分:0)

如果你在对象中创建一个静态变量,那么对于你将要制作的每个Vehicle类,它都是相同的,即使你要为你的抽象Vehicle类创建另一个子类。这是因为任何静态变量的“性质”。

我认为您希望使用非静态变量,以便对于抽象Vehicle类的任何子类的每个实例,您可以确定轮子的值,并按以下方式完成:

public abstract class Vehicle {
    public int wheels; //number of wheels on the vehicle
}

和任何子类:

public foo extends Vehicle{

     public void someMethode(){
         this.wheels = 2;
     }
}

您也可以为静态变量执行此操作,但是您将为Vehicle的任何子类的每个实例更改它

希望我帮助你

相关问题