Should I instantiate a collection or inherit from

2019-06-23 05:52发布

问题:

I've asked myself this question a number of times when creating classes, particularly those involving collections, but I've never come up with a satisfactory answer. It's a OOP design question.

For example, in a checkbook register program say I have a class of BankAccount. BankAccounts contain data involving the Name of the account, the Type of account (enum of Checking, Saving,...), and other data, but most importantly is a collection of the Adjustments (deposits or withdrawals) in the account.

Here, I have two options for keeping a collection of the Adjustments:

  1. Instantiate a collection and keep it as a member within the BankAccount class. This is like saying "BankAccount has a collection of Adjustments."
  2. Inherit from collection. This is like saying "BankAccount is a collection of Adjustments."

I think both solutions are intuitive, and, of course, both offer some advantages and disadvantages. For example, instantiating allows the class (in languages that allow only a single base class) to inherit from another class, while inheriting from collection makes it easy to control the Add, Remove, and other methods without having to write surrogate methods to 'wrap' those.

So, in such situations, which is a better approach?

回答1:

To me, a bank account has a collection of adjustments. A bank account is not a collection of adjustments, because it "is" much more than that: it also "is" a name and a type, etc.

So, in your case (and similar cases), I suggest you aggregate a collection inside your class.

In case of doubt, avoid inheritance. :-)

I can argument this further. In order to use inheritance properly, the subclass must satisfy Liskov's substitution principle; this means that, in your case, BankAccount should be a valid type anywhere a Collection is expected. I don't think that's the case, because a Collection probably exposes methods such as Add() and Remove(), whereas you will want to exert some control over adding and removing adjustments from your bank account rather than letting people add and remove them freely.



回答2:

Personally, I would say BankAccount has a collection of Adjustment. It will probably have other properties that aren't exclusively about what has been deposited or withdrawn ( customer, bank account type, etc ).

In terms of design, my BankAccount object would expose a late-loading property of type Adjustments.

In terms of use within the code, I would instantiate the bank account, and if I needed to know what had gone in and out of the account, I would use the exposed property. The BankAccount would be the primary object, responsible for providing the Adjustments related only to the instantiated account.



回答3:

Instantiate, definitely.

I agree with the other posters about Bank Account being "more" than just a collection of other items. Or maybe you jut picked an example which really screams out for "instantiate".

Examples:

  • What happens if your Bank Account needs a second collection of completely different items? (Example: collection of people who can operate on it, like husband and wife, for example, collection of credit cards, paypal accounts or anything else that can "operate" on your bank account).
  • Depending on the language a collection exposes too much of its info: if another object needs to access Adjustements... say for displaying your movements history on a web page you automatically expose your "collection" for injection, deletion and so on.


回答4:

I think getting overly caught up in semantics like "is this more is-a or has-a" is a little bit dangerous - at the end of the day, what matters is how well your design solved the problem, how maintainable it is, etc. In fact, personally, a turning point in the way I understand object oriented programming was letting go of "objects as nouns". Objects are, when you get down to it, an abstraction one level up from a function, nothing more or less.

This was a long way to say "has a". :-) Subclassing is complicated, using is easy.