我想扩展ArrayList,为特定类添加一些方法,这些类的实例将由扩展的ArrayList保存。下面是一个简化的说明性代码示例。
这对我来说似乎是明智的,但是我对Java还是很陌生,我看到了其他阻碍扩展ArrayList的问题,例如,扩展ArrayList和创建新方法。我对Java的理解不够了解。
在我先前的尝试中,我最终在ThingContainer中创建了许多实际上是传递给ArrayList的方法,因此扩展似乎更容易。
有没有更好的方法来做我想做的事情?如果是这样,应如何实施?
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);
}
}
}
该答案中的任何内容均不阻止扩展ArrayList;出现语法问题。存在类扩展,因此我们可以重用代码。
扩展类的通常反对意见是“赞成继承而不是继承”的讨论。扩展并非总是首选的机制,但它取决于您的实际工作。
根据要求编辑组成示例。
public class ThingContainer implements List<Thing> { // Or Collection based on your needs.
List<Thing> things;
public boolean add(Thing thing) { things.add(thing); }
public void clear() { things.clear(); }
public Iterator<Thing> iterator() { things.iterator(); }
// Etc., and create the list in the constructor
}
您不一定 需要 公开完整的列表界面,只需公开集合,或根本不公开。但是,不公开任何功能都会大大降低通用性。
在Groovy中,您可以仅使用@Delegate
批注自动构建方法。Java可以使用Project
Lombok
的@Delegate
注释执行相同的操作。我不确定Lombok如何公开该接口,或者是否公开。
我在使用glowcoder,在这种情况下,我看不到扩展存在任何根本上的错误-实际上,哪种解决方案更适合该问题是很重要的。
编辑有关继承如何违反封装的详细信息
有关更多详细信息,请参见Bloch的有效Java,第16项。
如果子类依赖于超类行为,并且超类的行为发生变化,则子类可能会中断。如果我们不控制超类,那就不好了。
这是一个具体的示例,它是用伪代码从书中摘录的(对不起,乔什!),并用大量的措辞解释(所有错误都是我的)。
class CountingHashSet extends HashSet {
private int count = 0;
boolean add(Object o) {
count++;
return super.add(o);
}
boolean addAll(Collection c) {
count += c.size();
return super.addAll(c);
}
int getCount() { return count; }
}
然后我们使用它:
s = new CountingHashSet();
s.addAll(Arrays.asList("bar", "baz", "plugh");
然后返回…三?不。六。为什么?
HashSet.addAll()
是在上实现的HashSet.add()
,但这是内部实现的细节。我们的子类addAll()
添加了三个calls
super.addAll()
,它们调用了add()
,也增加了count。
我们可以删除子类的addAll()
,但是现在我们依赖于超类实现的细节,而细节可能会改变。我们可以修改我们的代码addAll()
以迭代并调用add()
每个元素,但是现在我们正在重新实现超类行为,这违背了目的,并且如果超类行为依赖于对私有成员的访问,则并非总是可能的。
否则,超类可能会实现我们的子类未实现的新方法,这意味着该类的用户可能会通过直接调用超类方法而无意间跳过预期的行为,因此我们必须跟踪超类API以确定何时以及是否该子类应该改变。
扩展是专门设计的在 Yii 应用中随时可拿来使用的, 并可重发布的软件包。例如, yiisoft/yii2-debug 扩展在你的应用的每个页面底部添加一个方便用于调试的工具栏, 帮助你简单地抓取页面生成的情况。 你可以使用扩展来加速你的开发过程。 信息: 本文中我们使用的术语 "扩展" 特指 Yii 软件包。而用术语 "软件包" 和 "库" 指代非 Yii 专用的通常意义上的软件包。 使用扩展
vscode-react-native vscode-go
扩展为现有的类、结构体、枚举类型、或协议添加了新功能。这也包括了为无访问权限的源代码扩展类型的能力(即所谓的逆向建模)。扩展和 Objective-C 中的分类类似。(与 Objective-C 的分类不同的是,Swift 的扩展没有名字。) Swift 中的扩展可以: 添加计算实例属性和计算类型属性; 定义实例方法和类型方法; 提供新初始化器; 定义下标; 定义和使用新内嵌类型; 使现有的类型遵
概述 范例-hello-world 范例-word-count 范例-language-server 范例-调试器 调试-扩展 安装-扩展 范式-原则 测试-扩展 用我们的方法创造扩展
本页包含内容: 扩展语法 计算型属性 构造器 方法 下标 嵌套类型 扩展就是向一个已有的类、结构体或枚举类型添加新功能(functionality)。这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。扩展和 Objective-C 中的分类(categories)类似。(不过与Objective-C不同的是,Swift 的扩展没有名字。) Swift 中的扩展可以: 添加计算型属
Jinja2 支持扩展来添加过滤器、测试、全局变量或者甚至是处理器。扩展的主要动力是 把诸如添加国际化支持的常用代码迁移到一个可重用的类。 添加扩展 扩展在 Jinja2 环境创建时被添加。一旦环境被创建,就不能添加额外的扩展。要添加 一个扩展,传递一个扩展类或导入路径的列表到 Environment 构造函数的 environment 参数。下面的例子创建了一个加载了 i18n 扩展的 Jinj
一、本功能块说明 1.功能块简介 本功能块主要集中了全站各个模块的一些扩展属性,能够更加直观快速的进入所需的功能页面! 二、术语约定 1.导航栏 在本功能块下 导航栏 统一指整站的头部导航,既如下图所示: 2.菜单栏 在本功能块下 菜单栏 统一指扩展导航栏下的左侧菜单,既如下图所示:
http2协议强制规定了接收方必须读取并忽略掉所有未知帧(即未知帧类型的帧)。双方可以在逐跳原则(hop-by-hop basis)基础上协商使用新的帧,但这些帧的状态无法被改变,也不受流控制。 是否应该允许添加扩展的这个话题在制定http2协议的时候被反复讨论了很久,但在draft-12之后,最终尘埃落定确定了允许添加扩展。 但扩展不再是协议本身的一部分,它被记录在核心协议规范之外。现在已经有两