Let's say I'm creating an abstract class Fruit with function eat() and I want to make a few different classes implementing it. However, for the class Kiwi I also want to make a function peel() which wasn't defined in my abstract class.
Is it bad practice to make extra functions in a class implementing an abstract class? I know I could add it to the abstract class and just have it do nothing in the classes that don't use it, but seems bad if I have a lot of other classes it won't be useful in it.
Is it bad practice to make extra functions in a class implementing an abstract class?
Not at all!
Suppose we have the following classses:
class Fruit
{
public:
virtual void Eat() = 0; // pure virtual functions make the class abstract
}
class Berry : public Fruit
{
public:
void Eat() override
{ /* eat the berry... */ }
}
class Kiwi : public Fruit
{
public:
void Eat() override
{ /* eat the kiwi... */ }
void Peel()
{ /* peel the kiwi... */ }
}
We can certainly Eat()
any Fruit
we come across so it makes sense that all Fruit
objects can be eaten.
You wouldn't Peel()
a Berry
before eating it so there is no expectation that a Berry
can be Peel()
ed. That would be unnecessary for users that are handling a Berry
object anyways.
Before Eat()
ing a Kiwi
you should Peel()
it first, so anyone who is handling a Kiwi
object is going to expect the Peel()
function to be available and therefore Peel()
their Kiwi
before they Eat()
it.
Now let's say the user is blindfolded and given a Fruit* someFruit
pointer. They don't know whether it's a Berry
or a Kiwi
but they can certainly try { Eat(); }
it anyways because eating fruit always makes sense! If the Fruit
was actually a Kiwi
and they did not Peel()
it first then it is a good idea to have the Kiwi::Eat()
function throw an exception (throw "yuk!"
) or handle this unexpected usage gracefully.
Although this example is written really specifically about eating fruit, we can generally assume that the user of an object will know what functions are available for that object simply by knowing its type. And when the user does not know the object's type, then it is a good idea to implement some error-checking to handle its functions being used incorrectly.