扩展java ArrayList
我想扩展ArrayList,为一个特定类添加几个方法,该类的实例将由扩展的ArrayList保存。下面是一个简化的说明性代码示例 这对我来说似乎是合理的,但我对Java非常陌生,我看到了其他一些问题,例如,这些问题不利于扩展ArrayList。我对Java了解不够,无法理解反对意见 在我之前的尝试中,我最终在ThingContainer中创建了许多方法,这些方法基本上是通过ArrayList传递的,因此扩展似乎更容易 有没有更好的方法来做我想做的事?如果是,应如何实施扩展java ArrayList,java,arraylist,extend,Java,Arraylist,Extend,我想扩展ArrayList,为一个特定类添加几个方法,该类的实例将由扩展的ArrayList保存。下面是一个简化的说明性代码示例 这对我来说似乎是合理的,但我对Java非常陌生,我看到了其他一些问题,例如,这些问题不利于扩展ArrayList。我对Java了解不够,无法理解反对意见 在我之前的尝试中,我最终在ThingContainer中创建了许多方法,这些方法基本上是通过ArrayList传递的,因此扩展似乎更容易 有没有更好的方法来做我想做的事?如果是,应如何实施 import java.u
import java.util.*;
class Thing {
public String name;
public int amt;
public Thing(String name, int amt) {
this.name = name;
this.amt = amt;
}
public String toString() {
return String.format("%s: %d", name, amt);
}
public int getAmt() {
return amt;
}
}
class ThingContainer extends ArrayList<Thing> {
public void report() {
for(int i=0; i < size(); i++) {
System.out.println(get(i));
}
}
public int total() {
int tot = 0;
for(int i=0; i < size(); i++) {
tot += ((Thing)get(i)).getAmt();
}
return tot;
}
}
public class Tester {
public static void main(String[] args) {
ThingContainer blue = new ThingContainer();
Thing a = new Thing("A", 2);
Thing b = new Thing("B", 4);
blue.add(a);
blue.add(b);
blue.report();
System.out.println(blue.total());
for (Thing tc: blue) {
System.out.println(tc);
}
}
}
import java.util.*;
阶级事务{
公共字符串名称;
公共国际金额;
公共事物(字符串名称,整数金额){
this.name=名称;
本金额=金额;
}
公共字符串toString(){
返回字符串。格式(“%s:%d”,名称,金额);
}
公共int getAmt(){
返回金额;
}
}
类ThingContainer扩展了ArrayList{
公开无效报告(){
对于(int i=0;i
答案中没有任何内容会阻止扩展ArrayList;有一个语法问题。类扩展存在,因此我们可以重用代码
扩展类的常见反对意见是讨论。扩展并不总是首选的机制,但它取决于您实际在做什么
根据要求编辑合成示例
然后我们使用它:
s = new CountingHashSet();
s.addAll(Arrays.asList("bar", "baz", "plugh");
它回来了。。。三个?不。六。为什么?
HashSet.addAll()
是在HashSet.add()
上实现的,但这是一个内部实现细节。我们的子类addAll()
添加了三个调用super.addAll()
,它调用add()
,这也会增加计数
我们可以删除子类的addAll()
,但现在我们依赖于超类实现细节,这可能会改变。我们可以修改我们的addAll()
对每个元素进行迭代和调用add()
,但是现在我们正在重新实现超类行为,这违背了我们的目的,而且如果超类行为依赖于对私有成员的访问,可能并不总是可行的
或者一个超类可能实现一个我们的子类没有实现的新方法,这意味着我们的类的用户可以通过直接调用超类方法无意中绕过预期的行为,因此我们必须跟踪超类API以确定子类何时以及是否应该更改。我认为扩展arrayList是没有必要的
public class ThingContainer {
private ArrayList<Thing> myThings;
public ThingContainer(){
myThings = new ArrayList<Thing>();
}
public void doSomething(){
//code
}
public Iterator<Thing> getIter(){
return myThings.iterator();
}
}
以下是我的建议:
interface ThingStorage extends List<Thing> {
public int total();
}
class ThingContainer implements ThingStorage {
private List<Thing> things = new ArrayList<Thing>();
public boolean add(Thing e) {
return things.add(e);
}
... remove/size/... etc
public int total() {
int tot = 0;
for(int i=0; i < size(); i++) {
tot += ((Thing)get(i)).getAmt();
}
return tot;
}
}
接口内容存储扩展列表{
公共整数合计();
}
类ThingContainer实现ThingStorage{
private List things=new ArrayList();
公共布尔加法(e){
归还物品。添加(e);
}
…删除/大小/…等
公共整数总计(){
int-tot=0;
对于(int i=0;i
实际上不需要使用
report()
。toString()可以完成其余的工作。我喜欢你的最后一句话,“扩展并不总是首选的机制”。这就说明了一切。当涉及到类似这样的内容时,您需要编写java.util.List
,如果您仍然希望您的类扩展它,您必须创建一个成员List
,然后创建其他20个样板方法?所以,是的,通常我同意构图比继承更好。但我认为在这种情况下,继承是一种方式。我不明白我在这里如何实现组合。请详细说明。或者你是说普通的反对意见不适用于这里?@foosion To composite,你应该创建特定于应用程序的类,给它一个List
实例变量,并将类似列表的功能直接委托给列表。我会在答案中举一个小例子。@DaveNewton,啊哈。我就是这样开始的。然后我认为扩展会更好,因为我不需要实现add、clear等方法。扩展将免费提供给我。Jon Skeet的回答包括“我不会扩展ArrayList,除非我真的必须这样做,我更喜欢组合而不是继承”,或者“正如许多其他人所说,是的,您可以扩展类ArrayList,但这不是您通常应该做的事情;在Java中,这被认为是不好的实践。”。然而,从你和其他人的回答来看,我似乎误解了。就我个人而言,我倾向于避免对JDK类进行子类化,因为在实现中可能会有我无法控制的更改,或者可能会破坏扩展中我不知道的东西——偶尔会有一些微妙的“陷阱”当依赖超类行为时,如果我们没有实现细节,我们通常不会考虑,或者无法考虑。@DaveNewton,这个问题是否同样适用于使用JDK类?你的意思是只使用它们而不将它们子类化?这是不同的,因为类的方法的所有使用都由类控制。我将在几分钟内在我的答案中添加一个小的模糊。在这种情况下,如果我想从ArrayList添加、添加全部、清除、获取、删除等,我似乎需要创建相应的方法,而扩展则允许我从ArrayList使用这些方法,而无需进一步操作。我遗漏了什么吗?怎样才能在ThingCont中添加Thing
public class ThingContainer {
private ArrayList<Thing> myThings;
public ThingContainer(){
myThings = new ArrayList<Thing>();
}
public void doSomething(){
//code
}
public Iterator<Thing> getIter(){
return myThings.iterator();
}
}
public Interface ThingInterface {
public void doThing();
}
public OneThing implements ThingInterface {
public void doThing(){
//code
}
}
public TwoThing implements ThingInterface {
private String name;
public void doThing(){
//code
}
}
interface ThingStorage extends List<Thing> {
public int total();
}
class ThingContainer implements ThingStorage {
private List<Thing> things = new ArrayList<Thing>();
public boolean add(Thing e) {
return things.add(e);
}
... remove/size/... etc
public int total() {
int tot = 0;
for(int i=0; i < size(); i++) {
tot += ((Thing)get(i)).getAmt();
}
return tot;
}
}