Composition and inheritance
Đã giới thiệu| English | Ý nghĩa |
|---|---|
| inheritance/ɪnˈherɪtəns/ | The transfer of a deceased person's assets or rights to beneficiaries. |
| composition/ˌkɒmpəˈzɪʃn/ | composition |
| fragile base class | fragile base class |
One fix, a thousand wrong receipts
- A shop adds a loyalty bonus to its receipt total. The next day every discount receipt is wrong, though nobody touched the discount code.
- The discount class had copied the old total code instead of reusing it. How classes connect decides whether a fix in one place stays a fix everywhere.
Two ways to connect classes
- Inheritance 继承 says is-a: a
Memberis aPerson. Composition 组合 says has-a: aLibraryhas aCatalog. - Inheritance ties classes tightly. When a change to a base class breaks its children, that is the fragile base class 脆弱基类 problem.
super() builds the base first
super().__init__(...)runs the base class's set-up first, soPerson.__init__finishes before anyMemberline runs. Skip it andself._namedoes not exist whenMemberneeds it.
class Member(Person):
def __init__(self, name, card):
super().__init__(name)
self._card = card
self._loans = 0
Member.init starts with super().init(name) so that —
Độ khó 1/5 · 100 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
The chain is base-first: skip super() and self._name does not exist yet when Member needs it.
Put the steps of Member('Ana', 7) in order.
Độ khó 3/5 · 200 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
The base is always built first, so Member can rely on _name.
Override by delegating
- To change a base method, call it and adjust the result:
return super().total() - 10. The base's loyalty bonus then stays in your total. - Copying the base's code into the override makes a fork. The day the base gains a line, the copy goes stale: that was the receipt bug.
An override that copies the base method body —
Độ khó 1/5 · 100 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
The copied code is a fork: the base keeps changing while the copy stands still.
Receipt.total() gave 100. The base then gains a loyalty line that takes off 5. DiscountReceipt.total() is written as super().total() − 10. What does it return now?
Độ khó 2/5 · 140 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
The base now gives 95, and the override subtracts 10 from that. A copied body would still say 90.
Composition delegates
- A
Libraryholds itsCopyobjects and passes questions on:available()asks each partnot c.is_out()and counts the answers. - The library holds no borrowing logic of its own. Each part keeps its own rules.

Library and its Catalog are best connected by —
Độ khó 1/5 · 100 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
Has-a is composition: the whole owns parts and forwards calls; swap the part, keep the interface.
Swap the part, keep the whole
- Replace the list of copies with a database-backed collection and
Librarydoes not change: parts change, the whole keeps its interface. - Rule of thumb: inheritance for a true is-a, composition for everything else.
A Library class should inherit from list so that it can store its copies.
Độ khó 1/5 · 100 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
A library has copies; it is not a list. Composition keeps the list swappable and hides list methods the library should not offer.
Worked example: building and counting
Member('Ana', 7)startsMember.__init__, which callsPerson.__init__('Ana')to set_name; then_card = 7and_loans = 0. Twoborrow()calls make_loans2.- A library gets 5 copies and 2 are issued:
available()asks all 5 and returns 3.
A library holds 8 copies. 3 are issued, then 1 of those is given back. What does available() return?
Độ khó 2/5 · 140 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
2 copies are still out, so 8 − 2 = 6 are available.
Three common slips
- Inheriting just to reuse two methods. Use composition or a plain function.
- Forgetting
super().__init__. The base's attributes then never exist. - Copying base code into an override. The fork goes stale; delegate with
super().
Recap
- Is-a: inherit, and call
super()so the base is built first. - Has-a: compose, and delegate questions to the parts.
- Override by calling the base, never by copying it.