1

试图为此提出一个有意义的问题标题是很棘手的。我会准确地解释我想要做什么。

我创建了一个 Android 图形库,可以构建一个可能很大的Path对象列表。我现在需要为每个Path. 为此,我简单地进行了子类化Path(调用它PathSubclass)以提供额外的扩展数据字段。在一般用例中,只有极少数Path对象实际上会有额外的数据集。例如,可能有ArrayList几千个Path,但只有少数有额外的数据。在我开发库时,我想附加到每个库的额外数据量可能是Path会大幅增长。我很欣赏这可能是过早的优化,但我担心当附加数据很少填充并且使用该对象的相当大的集合时,将对象子类化以包含一些附加数据是无效的。

我想做的可能是开设一个ExtendedPathData与我的子类分开的课程Path。因此,每个Path子类只因需要一个mExtendedData成员而有点膨胀,在许多情况下null,除了那些Path需要额外数据的极少数对象外。我想这类似于View使用该方法通常将附加数据附加到 a 的setTag()方式。

是否有任何其他方法我应该考虑,因为任何原因更好?

4

2 回答 2

4

您可以使用组合而不是继承。

理念一

一个PathData类可能包含对 aPath和 a的引用ExtendedPathData

// encapsulate properly in your code, this is
// just a short sample
class PathData {
  public Path path;
  public ExtendedPathData data;
}

这使您可以将data成员设置为null。每个PathData实例的大小始终为两个引用。当 in 中的成员数量ExtendedPathData增加时,实际内存消耗仅对于PathData具有非 null 的实例才会增加data

想法 2

您可以通过使用具有两种实现的接口来减少一个参考:

interface PathData {
  Path path();
  ExtendedPathData data();
}

final class NullPathData implements PathData {
  Path path;
  public Path path() { return path; }
  public ExtendedPathData data() { return null; }
}

final class ExtendedPathData implements PathData {
  Path path;
  ExtendedPathData data;
  public Path path() { return path; }
  public ExtendedPathData data() { return data; }
}

由您决定拥有两个实现是否真的值得代码,因为您需要一个工厂方法来决定使用什么实现。每个实例一个4 字节的引用...

进一步的东西

如果ExtendedPathData不可变的并且可能存在许多相等的实例,您还可以通过公开使用实例池而不是公共构造函数的静态工厂方法来将它们汇集起来。

如果你有Joshua Bloch 的 Effective Java,这里有进一步的参考资料,详细解释了这些技巧(在更一般的上下文中):

  • Item 1 考虑静态工厂方法而不是构造函数
  • 第 16 条 组合优于继承
于 2013-01-07T09:58:10.667 回答
2

Path可以在下面的容器中存储子类不是继承的全部意义吗?

ArrayList<Path> pathList;

pathList.add(new Path());
pathList.add(new PathPlusPlus());

还是我不理解问题?

isinstanceof正如@assylias 建议的那样,要消除丑陋的调用,您可以向基类添加一个getter,它返回扩展数据。在基类本身中它会返回null,而在子类中它会返回相关数据。

于 2013-01-07T10:00:50.063 回答