我应该扩展 ArrayList (is-a) 还是应该将其包含为成员 (has-a)?

发布于 2024-10-22 06:00:12 字数 391 浏览 2 评论 0原文

我正在制作一个简单的程序来维护一个数字列表,并且我希望这个列表也有一个名称。哪种方法是最好的方法:让我的列表类扩展 ArrayList 还是让它包含 ArrayList 成员?在这两种情况下,当然都会有一个“name”字符串成员。

第一种方法意味着我只需要实现一个 getter & 方法。名称的设置器,但我认为这会将我的类与特定实现联系得太紧密?例如,如果我想稍后使用 Vector,那么我必须在各处更改代码。

第二种方法可以更轻松地更改实现,但现在当然变得非常烦人,因为我必须实现一堆包装器。

我已经阅读了有关继承与组合的 SO 帖子,并且由于我的列表是 ArrayList 的一种类型,因此我倾向于第一种方法。但是,由于我扩展 Collection 类与扩展通用类,所以讨论是否有任何差异?还是我想太多了?

I'm making a simple program that maintains a list of numbers, and I want this list to also have a name. Which is the best approach: have my list class extend ArrayList or have it include an ArrayList member? In both cases, there would of course be a "name" String member.

The first approach means I only have to implement a getter & setter for the name, but I think this would tie my class too closely to a particular implementation? For example, if I wanted to later use a Vector, than I would have to change code everywhere.

The second approach would make it easier to change the implementation, but of course becomes quite annoying for now, since I have to implement a bunch of wrappers.

I've read the SO posts regarding inheritance vs. composition, and since my list is a type of ArrayList, I am leaning towards the first approach. However, is there any differences to the discussion because I'm extending a Collection class vs extending a general class? Or am I over-thinking this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

只有影子陪我不离不弃 2024-10-29 06:00:12

从长远来看,加入为会员通常比延长会员资格更好。这样,您想要允许的内容就更加明确,从而更容易测试并保持班级的联系。如果您只是扩展 ArrayList,那么它可能并不总是按您的预期使用。当然,权衡是您必须为您想要允许的所有内容显式创建传递方法。或者(或另外),您可能希望提供一种方法来获取基础 List,您可以用不可变集合包装该 List,以保护它免受类控制之外发生的更改的影响。

In the long run it's generally better to include as a member than extend. This way it's more explicit what you want to allow, making it easier to test and hold to the contact of the class. If you simply extend ArrayList then it might not always be used as you intended. The trade-off of course is that you'll have to explicitly create pass-through methods for everything you do want to allow. Alternatively (or additionally) you might want to provide a method to get the underlying List, which you could wrap with an immutable collection to safeguard it from changes happening outside of the control of your class.

离鸿 2024-10-29 06:00:12

为了两全其美,请使用 Guava Guava 转发列表。这是一个简单的例子:

public class NamedList<E> extends ForwardingList<E> implements RandomAccess {
  // could also let the user provide the delegate list
  private final List<E> delegate = Lists.newArrayList();
  private String name;

  @Override protected List<E> delegate() {
    return delegate;
  }

  // constructors, getter, setter
}

顺便说一句,扩展具体集合实现而不是使用组合的陷阱在Effective Java第 16 项(第 2 版)“优先使用组合而不是继承”中进行了讨论。提到的几个问题之一与超类中方法之间的交互相关的意外行为有关(例如 addaddAll)。

Guava 的 Forwarding* 类是此处建议的解决方案的实现。

For the best of both worlds, use a Guava ForwardingList. Here's a simple example:

public class NamedList<E> extends ForwardingList<E> implements RandomAccess {
  // could also let the user provide the delegate list
  private final List<E> delegate = Lists.newArrayList();
  private String name;

  @Override protected List<E> delegate() {
    return delegate;
  }

  // constructors, getter, setter
}

By the way, the pitfalls of extending a concrete collection implementation rather than using composition are discuseed in Effective Java item 16 (in 2nd Ed.) "Favor composition over inheritance." One of the several issues mentioned has to do with unexpected behavior related to the interaction between methods in the superclass (e.g. add and addAll).

Guava's Forwarding* classes are an implementation of the solution suggested there.

臻嫒无言 2024-10-29 06:00:12

两者都不是更好,正如您提到的,这是一种权衡。

如果你进行聚合(has-a),你必须包装你要使用的成员的所有功能(即实现调用它们的函数)

如果你进行继承,很多函数会添加到你的新类中,这可能是不必要的,并且还需要实现抽象函数。

如果你在 C++ 环境中,私有继承是一个选择,但是两者都有优点和缺点

Neither is better, its a trade-off as you mentioned.

If you do aggregation (has-a) you have to wrap all the functionality of the member you're going to use (i.e implement functions that call them)

If you do inheritance, A lot of functions are added to your new class which might be unneccessary, And you need to implement abstract functions as well.

If you were in a C++ environment, private inheritance would be an option, But here both have pros and cons

怪我太投入 2024-10-29 06:00:12

成分-HAS-A。我更喜欢用它来收藏各种风格的衣服。

Composition - HAS-A. I prefer it for collections of all stripes.

对你的占有欲 2024-10-29 06:00:12

@AbiusX 是对的,需要权衡。但我用第一种方法来解决你的担忧。请考虑以下内容并让我知道这种方法存在哪些问题:

public class MyClass implements List
{
    private String name;
    private List myList = new ArrayList();

    public MyClass(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }

    public void setName()
    {
        return name;
    }

    @Override
    public void add(int index, Object element)
    {
        myList.add(index,element);
    }

    @Override
    public boolean add(Object o)
    {
        myList.add(o);
    }

    @Override
    public boolean addAll(Collection c)
    {
        myList.addAll(c);
    }

    //so on for rest of methods in List interface
}

如果您想让数字类型安全,我们还可以包含泛型。

@AbiusX is right there is trade off. But I have asollution for your worry with first approach. Please consider following and let me know what problems are with this approach:

public class MyClass implements List
{
    private String name;
    private List myList = new ArrayList();

    public MyClass(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }

    public void setName()
    {
        return name;
    }

    @Override
    public void add(int index, Object element)
    {
        myList.add(index,element);
    }

    @Override
    public boolean add(Object o)
    {
        myList.add(o);
    }

    @Override
    public boolean addAll(Collection c)
    {
        myList.addAll(c);
    }

    //so on for rest of methods in List interface
}

We can also include Generics if you want to make it type safe for numbers.

人海汹涌 2024-10-29 06:00:12

继承 ArrayList 不是一个好主意,您需要一个强有力的理由才能这样做。像 Collections 这样的实用程序类提供了多种必要的功能,因此您确实需要添加一些额外的必需功能来证明子类化的合理性,就像一个非常知名的类一样。

Inheriting ArrayList is not a good idea, you need a strong reason to do that. Utility classes like Collections provide the necessary functionality in several flavors, so you really need to add some extra required functionality in order to justify the subclassing, as is a very well-know class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文