Определение дополнительных функций, специфичных для реализации, в классе, реализующем абстрактный класс - PullRequest
0 голосов
/ 05 июня 2019

Допустим, я создаю абстрактный класс Fruit с функцией eat () и хочу создать несколько различных классов, реализующих его. Однако для класса Kiwi я также хочу создать функцию peel (), которая не была определена в моем абстрактном классе.

Это плохая практика - создавать дополнительные функции в классе, реализующем абстрактный класс? Я знаю, что мог бы добавить его в абстрактный класс и просто сделать так, чтобы он ничего не делал в классах, которые его не используют, но, кажется, плохо, если у меня много других классов, это будет бесполезно.

1 Ответ

1 голос
/ 05 июня 2019

Это плохая практика - создавать дополнительные функции в классе, реализующем абстрактный класс?

Совсем нет!

Предположим, у нас есть следующие классы:

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... */ }
}

Мы, безусловно, можем Eat() любой Fruit, с которым мы сталкиваемся, поэтому имеет смысл, что все Fruit объекты могут быть съедены.

Вы не станете Peel() a Berry до того, как съесть его, поэтому не стоит ожидать, что Berry может быть Peel() ed. Это было бы ненужным для пользователей, которые в любом случае обрабатывают объект Berry.

До Eat() с Kiwi вы должны Peel() сначала, поэтому любой, кто обрабатывает объект Kiwi, будет ожидать, что функция Peel() будет доступна, и поэтому Peel() их Kiwi прежде чем они Eat() это.

Теперь предположим, что у пользователя завязаны глаза и ему дан указатель Fruit* someFruit. Они не знают, является ли это Berry или Kiwi, но они в любом случае могут try { Eat(); }, потому что есть фрукты всегда имеет смысл! Если Fruit был на самом деле Kiwi и они не Peel(), то вначале было бы хорошо, если бы функция Kiwi::Eat() вызвала исключение (throw "yuk!") или корректно обработала это неожиданное использование.

Хотя этот пример действительно написан специально для поедания фруктов, мы обычно можем предположить, что пользователь объекта будет знать, какие функции доступны для этого объекта, просто зная его тип. А когда пользователь не знает тип объекта, то неплохо реализовать некоторую проверку ошибок, чтобы неправильно обрабатывать его функции.

...