簡體   English   中英

java中靜態覆蓋的替代方法

[英]Alternative to static overriding in java

我已經為此苦苦掙扎了一段時間。 我想定義一組有限的類型,其中一些類型是其他類型的子類型,其中每種類型都由其屬性值定義。 然后這些類型將用於訪問它們的屬性,並通過工廠方法來創建它們的實例。

現在可能沒有多大意義,所以假設我有這段代碼。

abstract class Car {
    final int seats;
    final int maxSpeed;
    ...
}

abstract class DeliveryCar extends Car {
    final int maxload;
    ...
}

現在我想要擁有諸如超類型Car FamilyCarSportsCar和超類型DeliveryCar HeavyTruck之類的類型,每個類型都有多個實例,困難的部分是實例變量不應該真正是“實例”變量 - 它們應該具有相同的值每個FamilyCar ,然后是每個SportsCar一些其他值,以及每個HeavyTruck其他值,它們應該可以在沒有實例的情況下訪問。 例如,我希望能夠編寫:

System.out.print("Sports cars' max. speed: " + SportsCar.maxSpeed);

我想到了一些但沒有解決的事情:

  • 靜態值,但 java 不允許覆蓋靜態成員
  • 枚舉,但在 java 中沒有枚舉的子類化,因此每個不是DeliveryCar Car都必須具有maxload和可能的其他成員
  • 模擬枚舉,如下所示:
class CarType {
    final int seats;
    final int maxSpeed;
    ...
    static final CarType FAMILY_CAR = new CarType(5, 180);
    static final CarType SPORT_CAR = new CarType(2, 280);
    ...
    CarType(int seats, int maxSpeed) {
    ...
}

class DeliveryCarType extends CarType {
    final int maxload;
    ...
    static final DeliveryCarType HEAVY_TRUCK = new DeliveryCarType(3, 150, 500)
    ...
    DeliveryCarType(int seats, int maxSpeed, int maxLoad) {
    ...
}

它會做我需要的事情,但它也會有效地寫一些類似DeliveryCar.SPORTS_CAR東西。

我不確定我試圖實現的設計中是否存在一些基本缺陷,但它讓我非常煩惱,因為我似乎無法解決一些可以通過我認為其他語言的可覆蓋靜態成員解決的問題(例如Objective-C)實現。

編輯:我也閱讀了這個討論(以及其他),但那里的想法似乎都沒有解決我的問題。

首先,關於什么不起作用的重要說明(純靜態的東西):

public static class Car {
    public final static String NAME = "Car";
    public static String getName() { return NAME; }
}

public static class SportsCar extends Car {
    public final static String NAME = "SportsCar";
    public static String getName() { return NAME; }
}

public static void main(String[] args) {
    Car c0 = new Car();
    System.out.println(c0.NAME);
    System.out.println(c0.getName());
    //  both print "Car"

    SportsCar c1 = new SportsCar();
    System.out.println(c1.NAME);
    System.out.println(c1.getName());
    // both print "SportsCar"

    Car c2 = new SportsCar();
    System.out.println(c2.NAME);
    System.out.println(c2.getName());
    // both print "Car" because c2 ""doesn't know"" that it's really a 'SportsCar'
    // this is an issue with your need for polymorphism with these values
}

如果您想要多態性,那么您需要有返回靜態值的實例方法,並覆蓋實例方法以返回其類的更新靜態值。 也許是這樣的:

public static class Car {
    public final static String NAME = "Car"; 
    public final static int MAX_SPEED = 90;

    public String getName() { return NAME; }
    public int getMaxSpeed() { return MAX_SPEED; /* Car.MAX_SPEED */ }
    public String toString() { return getName() + ": maxSpeed= " + getMaxSpeed(); }
}

public static class SportsCar extends Car {
    @SuppressWarnings("hiding") public final static String NAME = "SportsCar";
    @SuppressWarnings("hiding") public final static int MAX_SPEED = 120;

    @Override public String getName() { return NAME; /* SportsCar.NAME */}
    @Override public int getMaxSpeed() { return MAX_SPEED; /* SportsCar.MAX_SPEED */ }
    // ** no new fields so just inherit 'toString()'
}

public static class DeliveryCar extends Car {
    @SuppressWarnings("hiding") public final static String NAME = "DeliveryCar";
    @SuppressWarnings("hiding") public final static int MAX_SPEED = 70;
    /* new field ........... */ public final static int MAX_LOAD = 250;

    @Override public String getName() { return NAME; /* DeliveryCar.NAME */}
    @Override public int getMaxSpeed() { return MAX_SPEED; /* DeliveryCar.MAX_SPEED */}
    /* new */ public int getMaxLoad() { return MAX_LOAD; /* DeliveryCar.MAX_LOAD */ }

    @Override public String toString() { return getName() + ": maxSpeed= " + getMaxSpeed() + ", maxLoad= " + getMaxLoad(); }
}

public static class DeliveryTruck extends DeliveryCar {
    @SuppressWarnings("hiding") public final static String NAME = "DeliveryTruck";
    @SuppressWarnings("hiding") public final static int MAX_LOAD = 1000;

    @Override public String getName() { return NAME; /* DeliveryTruck.NAME */}
    @Override public int getMaxLoad() { return MAX_LOAD; /* DeliveryTruck.MAX_LOAD */ }
    // ** no new fields so just inherit 'toString()'
}


public static void main(String[] args) {
    List<Car> list = Arrays.asList(new Car(), new Car(), new SportsCar(), new DeliveryCar(), new DeliveryTruck(), new SportsCar());
    for(Car car : list) {
        System.out.println(car);
    }
    System.out.println("Static Car maxSpeed = " + Car.MAX_SPEED);
    // warning, should access through DeliveryCar.MAX_SPEED since DeliveryTruck doesn't redefine it.
    System.out.println("Static DeliveryTruck maxSpeed = " + DeliveryTruck.MAX_SPEED);
}

我不是特別喜歡它,但它有效......如果沒有別的,這至少是一個頭腦風暴,希望能引導我們找到更好的解決方案。 我很想聽聽你是否有更好的想法。

您不需要靜態字段,只需使用常規受保護(或公共)字段。 如果您想確保其他子類型無法覆蓋它,您可以在子類中將其設為 final...

abstract class  Car {
     protected int max = 5;
}

class Family extends Car {
    protected final int max = 10;
}

class Sport extends Car {
    protected final int max = 100;
}

class Other extends Car {
}

public static void main(String[] args) {
  System.out.println(new Family().max);
  System.out.println(new Sport().max);
  System.out.println(new Other().max);
}

給出輸出:10 100 5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM