Imagine that we want to extend our bookstore classes to support several discount strategies. In addition to a bulk discount, we might offer a discount for purchases up to a certain quantity and then charge the full price thereafter. Or we might offer a discount for purchases above a certain limit but not for purchases up to that limit.
Each of these discount strategies is the same in that it requires a quantity and a discount amount. We might support these differing strategies by defining a new class named Disc_quote
to store the quantity and the discount amount. Classes, such as Bulk_item
, that represent a specific discount strategy will inherit from Disc_quote
. Each of the derived classes will implement its discount strategy by defining its own version of net_price
.
Before we can define our Disc_Quote
class, we have to decide what to do about net_price
. Our Disc_quote
class doesn’t correspond to any particular discount strategy; there is no meaning to ascribe to net_price
for this class.
We could define Disc_quote
without its own version of net_price
. In this case, Disc_quote
would inherit net_price
from Quote
.
However, this design would make it possible for our users to write nonsensical code. A user could create an object of type Disc_quote
by supplying a quantity and a discount rate. Passing that Disc_quote
object to a function such as print_total
would use the Quote
version of net_price
. The calculated price would not include the discount that was supplied when the object was created. That state of affairs makes no sense.