- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图在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();
}
}
我不想在每个子类中重新创建每个类和变量。这有点违背了拥有 parent 的目的。
这是否可能,或者我是否必须为每个人构建它?我想我也许可以用 <T>
来做到这一点就像他们这样做的方式 List<T> ...
但我对此了解不够,甚至不知道它叫什么。
任何帮助都会很棒。
最佳答案
其他答案中概述了如何做到这一点的技术解决方案。
但除此之外,我在这里有一个明显的非答案:不要这样做!
假设我们正在谈论“现实世界”的 OO 设计和最佳实践 - 那么问题中显示的代码将提供数小时的广泛“为什么不这样做 OO”讨论的 Material :
静态在良好的 OOP 中更像是一种异常。将字段暴露给子类的想法也是如此。 OOP 中的关键是多态性——通过子类化和重写方法来改变行为的能力。一旦开始使用静态就告别多态性。然后:字段是一个实现细节 - 它们不应该被其他类使用。
如果您忽略这些基本规则,您最终会得到到处都是紧密耦合的代码。使用不同类的想法是构建可以尽可能独立工作的独立单元。
你的方法归结起来与此完全相反。您很可能无法在一个地方进行单一更改 - 因为您很可能在大多数时间都必须更改其他地方。
从这个意义上说:退后一步,重新审视您想要解决的问题。然后提出一个遵循良好的 OOP 实践的设计——而不是否定它们。
给出一些更实际的建议:乍一看,在类中拥有一个计算实例数量的静态列表可能看起来非常方便。但这直接违反了Single Responsibility Principle 。你看,真正的“业务逻辑对象应该有一个非常明确的目的。你创建类,并实例化这些类的对象,因为它在你的模型中有意义。你的模型,是你的“现实世界”事物的模型。打算代表。来自那里:狗或猫知道其他狗或猫吗?不是真的。你的代码也应该如此。如果你有充分的理由保留“实例化对象列表” - 然后为此使用特定的类。您试图使动物也成为动物列表管理器。为了实现您零的需求无论如何使用静态。您可以使用工厂来创建对象,并且该工厂可以使用 ListKeeper 实现。只是为了记录:您知道,简单地将引用保留在这样的列表中会导致内存泄漏?因为这些对象永远不会变成垃圾,所以你只需不断添加新对象...
所以,再说一次:您不需要或不想要那个静态继承列表 - 因为在一个好的面向对象模型中,您将有一个不同的类负责管理这些事情。
想象一下,在某一时刻,单个列表不再起作用。也许您想将不同的狗组织到不同的列表中?这意味着您必须更新 Dog 类 - 尽管“在不同列表中组织 Dogs”与 Dog 类本身无关。
然后你希望你的类是 open for extension but closed for modification 。在你的情况下,这宁愿看起来像这样:
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();
换句话说:只有在有充分理由的情况下才使用“ protected ”和“字段继承”。因为,正如所说:字段是实现细节 - 并且没有其他类(无论是你的 child )应该知道这些事情。或者您是否让您的 child 可以使用您的信用卡?不 - 如果您提供了一个“ setter/getter ”,可以让您保持一定程度的控制。您不能只是把钱包放在 table 上然后告诉您的 child :“现在就可以随意使用我的信用卡了”。
关于Java:静态父/子变量和方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48467991/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!