[英]Java — Initializing superclass variables in subclasses?
好的,例如,假設我有一個名為“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
}
如果“車輪”是靜止的,則只有一個,它將同時適用於所有車輛。 因此,三輪車,摩托車,18輪卡車和福特都將擁有相同數量的車輪。
這對我來說沒有意義。 最好讓'wheels'成為父類中的實例變量,但每個子類都適當設置。
但你可以試試
Vehicle.wheels = 2;
注意:自從您添加到問題中后,我正在添加我的答案。
我喜歡你在每個子類中都有靜態的想法。 但你應該把它們變成私人的。 然后把一個抽象方法放在父類(Vehicle)中
public abstract BufferedImage getSprite();
然后每個直接子類必須具有相同的方法,並且它可以返回私有靜態變量。
使變量保持靜態,因此您只需加載一次。 將它們設為私有,以便類本身之外的代碼不會愚弄它並引入錯誤。 如果可能的話,你可以讓它們成為'final',這樣類中的代碼就不能在事后改變它並引入bug。 (一個'最終'變量不能改變它的值,但它的值的內容可能會改變。所以'最終'不是很好,因為它可能。)
你要做的事情從根本上是有缺陷的。 你可以讓Motorcycle
初始化一次wheels
:
// Static initializer
static
{
wheels = 2;
}
...或每次創建實例時:
// Instance initializer
{
wheels = 2;
}
但是只有一個變量 - 不是Motorcycle
一個變量 , Truck
等的變量 。如果你對Truck
和Motorcycle
做同樣的事情,那么最后初始化的那個將“贏”。
目前尚不清楚你想如何使用這個字段 - 但是如果你只有一個靜態字段,那么它只會有一個值 - 而不是每個子類一個。
靜態成員只定義一次,並且對於每個擴展類都是通用的。 更改其中一個中的值將影響所有其他值。 這就是我相信你真正想要實現的目標:
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);
}
}
我認為有一個更優雅的方式來做到這一點
我要提議的內容仍然受到您需要實例的限制。 我沒有看到任何解決方法,因為你希望wheels
作為超類的一部分暴露,但wheels
的值依賴於子類和Vehicle
內部沒有沒有實例的子類類型的概念。
在我看來,在這種情況下,“輪子”既不是靜態的也不是非靜態的。 它是類元數據 。 指定類元數據的Java方法是通過注釋。
你需要的是一個用戶定義的注釋,如下所示:
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface VehicleMetadata{
int wheels();
}
然后,您按如下方式注釋Motorcyle:
@VehicleMetadata(2)
public class Motorcycle extends Vehicle {}
在超類中,您提供了一個獲取annotation屬性值的訪問器。 我建議你使用“懶惰評估”方法,這樣每次需要時都不會使用反射。
注意使用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 ;
}
在我看來,這是最優雅的解決方案。
原始類聲明:
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分配給wheel並且有一個getter方法來返回wheel的值)。
Motorcycle cycle = new Motorcycle();
Truck pickup = new Truck();
...
System.out.println("Motorcycle has " + cycle.getWheels() + " wheels.");
將打印:
摩托車有4個輪子。
也許你想考慮一下你正在使用的構造函數。
public Vehicle(int wheels) {
this.wheels = wheels;
}
public Motorcycle(int wheels) {
super(wheels);
}
public Motorcycle cycle = new Motorcycle(2);
Motorcycle使用知道如何處理參數的超級構造函數。 它會自動將車輪設置為2。
如果在對象中創建一個靜態變量,那么對於您將要創建的每個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的任何子類的每個實例更改它
希望我能幫助你
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.