簡體   English   中英

Java:靜態父/子變量和方法

[英]Java: Static Parent/Child variables and methods

我試圖在Java中創建一個父類,該類將靜態變量傳遞給它的每個子類,以便每個子類都有自己的副本。

這是代碼示例:

import java.util.*;

public class JavaFiddle {
    public static void main(String[] args) {
        Animal rex = new Dog("Rex", 3.2, 'M');
        Animal luna = new Dog("Luna", 1.2, 'M');
        Animal sadie = new Dog("Sadie", 0.1, 'F');
        Animal daisy = new Dog("Daisy", 5.9, 'F');
        Animal snowball = new Cat("Snowball", 3.8, 'M');
        Animal tiger = new Cat("Tiger", 9.8, 'M');

        System.out.println(Dog.getCount()); // output => 4
        System.out.println(Cat.getCount()); // output => 2
    }
}

class Animal {
    protected static final List<Animal> list = new ArrayList<>(); // Each child class should get it's own static list

    String name;
    double age;
    char gender;


    Animal (String name, double age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;

        list.add(this); // This should add the child object to the the static list in the child class
    }

    public static int getCount() { // This should return the size of the static list for the child class
        return list.size();
    }
}

class Dog extends Animal {
    protected static final List<Dog> list = new ArrayList<>(); // I don't want to have to add this for each child class. It should just get a copy from the parrent.

    Dog (String name, double age, char gender) {
        super(name, age, gender);

        list.add(this); // I don't want to have to add this for each child class. It should just be added from the parrent.
        // other stuff
    }

    public static int getCount() { // I don't want to have to add this for each child class. It should just get a copy from the parrent.
        return list.size();
    }
}

class Cat extends Animal {
    protected static final List<Cat> list = new ArrayList<>(); // I don't want to have to add this for each child class. It should just get a copy from the parrent.

    Cat (String name, double age, char gender) {
    super(name, age, gender);

        list.add(this); // I don't want to have to add this for each child class. It should just be added from the parrent.
        // other stuff
    }

    public static int getCount() { // I don't want to have to add this for each child class. It should just get a copy from the parrent.
        return list.size();
    }
}

我不想在每個子類中重新創建每個類和變量。 那會破壞有父母的目的。

這是否有可能,或者我將不得不為每個構建它嗎? 我想我可以用<T>做到這一點,就像他們處理List<T> ...但是我對此並不甚了解,甚至被稱為什么。

任何幫助都會很棒。

其他答案中概述了如何做到這一點的技術解決方案。

但是除此之外,我這里還有一個明確的答案 :不要這樣做!

假設我們正在談論“現實世界”的OO設計和最佳實踐-那么問題中顯示的代碼將為數小時的“為什么不這樣做OO”討論提供材料:

靜態在良好的OOP中更像是一種異常。 將字段暴露給子類的想法也是如此。 OOP中的關鍵是多態性-通過子類化和覆蓋方法改變行為的能力。 一旦開始使用靜態,請告別多態。 然后:字段是實現細節-其他類不應使用它們。

如果您忽略了這些基本規則,那么最終的代碼將緊密地結合在一起。 使用不同類的想法是建立獨立的單元,這些單元可以盡可能孤立地工作。

您的方法可以歸結為與之完全相反。 很有可能您將無法在一個位置上進行單個更改-因為您很可能在大多數時間不得不更改其他位置。

從這個意義上講:退后一步,再次查看您要解決的問題。 然后提出一個遵循良好OOP慣例的設計-而不是否定它們。

給出一些更實際的建議:乍一看,在類中包含一個統計實例數量的靜態列表可能看起來非常方便 但這直接違反了單一責任原則 您會看到,真正的“業務邏輯對象”應該有非常不同的用途。您創建類,並實例化這些類的對象,因為它在您的模型中是有意義的。並且您的模型是“現實世界”對象的模型來自那里:一只狗或貓知道其他的狗或貓嗎?不是真的。您的代碼也應該如此。如果您有充分的理由保留“實例化對象列表”,則使用一個特定的類來表示。為了使動物成為動物管理者列表,並且為了實現對使用靜態的需求,您可以使用工廠來創建對象,而該工廠可以利用該對象ListKeeper實現。僅作記錄:您了解僅將引用保存在這樣的列表中會導致內存泄漏嗎?因為這些對象永遠不會變成垃圾,因此您只需添加新對象...

因此,再次:您不需要或不需要該靜態繼承列表-因為在一個好的OO模型中,您將擁有一個單獨的類來管理此類事情。

例如,想象一下, 單個列表不再起作用。 也許您想在不同的列表中組織不同的狗? 這意味着您必須更新Dog類-盡管“在不同列表中組織Dog”與Dog類本身無關

然后,您希望您的類為擴展而打開,但為修改而關閉 在您的情況下,它看起來像這樣:

public abstract class Animal {
  private final String name;

  public Animal(String name) { 
    this.name = Objects.requireNonNull(name, "name must not be null"); }

  private final String getName() { return name; }

  public abstract foo();
  public abstract String getEnhancedName();

換句話說:僅在有充分理由的情況下才使用保護和“字段繼承”。 因為,正如前所述:字段是實現的詳細信息 -其他任何類(您的子女)都不應該知道這些事情。 還是讓孩子們可以使用信用卡? 否-如果您為此提供了一個“獲取器”,則可以讓保持一定的控制權。 您不只是將錢包放在桌子上並告訴孩子們:“現在就去隨便使用我的信用卡”。

import java.util.*;

public class Animal {

    protected static final List<Animal> list = new ArrayList<>(); // Each child class should get it's own static list

    String name;
    double age;
    char gender;

    Animal(String name, double age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;

        list.add(this); // This should add the child object to the the static list in the child class
    }

    public static int getCount() { // This should return the size of the static list for the child class
        return list.size();
    }
}

class Dog extends Animal {
    Dog(String name, double age, char gender) {
        super(name, age, gender);

    }
}

class Cat extends Animal {   
    Cat(String name, double age, char gender) {
        super(name, age, gender);
    }

    public static void main(String[] args) {
        Animal rex = new Dog("Rex", 3.2, 'M');
        Animal luna = new Dog("Luna", 1.2, 'M');
        Animal sadie = new Dog("Sadie", 0.1, 'F');
        Animal daisy = new Dog("Daisy", 5.9, 'F');
        Animal snowball = new Cat("Snowball", 3.8, 'M');
        Animal tiger = new Cat("Tiger", 9.8, 'M');

        for(Animal anim : Animal.list){
            if(anim instanceof Dog){
                System.out.println("Dog");
            }else if(anim instanceof Cat){
                System.out.println("Cat");
            }
        }
    }
}

輸出:狗狗狗狗貓貓貓

您可以在Animal使用地圖

public class Animal {
  private static final Map<Class, List<Animal>> map = new HashMap<>();

  Animal (String name, double age, char gender) {
    //...
    map.computeIfAbsent(this.getClass(), key -> new ArrayList<>()).add(this);
  }

  public static int getCount(Class clazz) {
    return map.get(clazz).size();
  }
}

public class Dog extends Animal {
   Dog(String name, double age, char gender) {
      super(name, age, gender);
   }
   //optional
   public static int getCount() {
     return Animal.getCount(Dog.class);
  }
}

main您將擁有:

System.out.println(Animal.getCount(Dog.class)); // output => 4
System.out.println(Animal.getCount(Cat.class)); // output => 2

//or
System.out.println(Dog.getCount()); // output => 4
System.out.println(Cat.getCount()); // output => 2

暫無
暫無

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

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