[英]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.