Пусть один класс начинает брать на себя слишком много обязанностей.
class ArtLebedev : public DesignStudio, public BookPublisher {
int money;
Fun fun;
};
Где как, а в ОО рецепт на все один: новый класс. Постараемся, однако, не делать резких движений и на первое время сохранить близкий контакт с отпочковавшимся классом. Оформим его как
(
Read more... )
Comments 11
Как насчёт:
class ArtLebedev : public DesignStudio {
int money;
Fun fun;
BookPublisher publisher;
void publish_good_book();
};
void ArtLebedev::publish_good_book() {
publisher.publish_good_book();
money -= 1000;
fun++;
}
// за ошибки не ручаюсь - с++ - не родной язык.
Reply
другое дело, что интерфейс Publisher'а по прежнему остался у главного класса (то есть публичный метод publish_good_book()).
предположим, что на самом деле там было 10 публичных методов. это могла быть одна из целей -- перенести все эти методы во вложенный классу. особенно это интересно становится, когда методы виртуальные.
Reply
Может быть:
class ArtLebedev : public DesignStudio {
int money;
Fun fun;
};
class ArtLebedevBookPublisher : public ArtLebedev {
...
};
Но опять же, в зависимости от предметной области.
Reply
А вот наследование одного класса от другого только ради доступа к чему-то меня немного смущает.
Reply
Уродуем название настолько, что это даже запрещено стандартом =)
Одна из полезных функций, которую мы тут теряем, - это возможность скастовать ArtLebedev к BookPublisher.
Можно жить так.
Написать два класса ArtLebedevDesign : DesignStudio и ArtLebedevPublisher : BookPublisher.
Далее class ArtLebedev : public ArtLebedevDesign, public ArtLebedevPublisher {};
В ArtLebedevDesign делаем приватную функцию
ArtLebedevPublisher & publisher() { return static_cast< ArtLebedev & >(*this); }
а в ArtLebedevPublisher - аналогичную функцию
ArtLebedevDesign & design() { return static_cast< ArtLebedev & >(*this); }
Таким образом:
0. Код разделён
1. оба класса становятся равноправными
2. касты сохраняются
3. с точки зрения остального кода ничего не изменилось
4. нет reinterpret_cast-ов и прочего
Далее, чтобы код было не сломать, делаем у ArtLebedevPublisher ( ... )
Reply
Reply
=) Да, но у этого слова ещё дохрена различных значений.
> насколько я привык, программа, где все кастуется во все, из приятного волшебства быстро превращается в кошмар
Согласен. Но тут это, ИМХО, оправдано, т.к. выполняется отношения ArtLebedev IS DesignStudio и ArtLebedev IS BookPublisher.
> собственно, этот пост и был про то, как начать разделять два класса, но в C++.
Да, просто в вашем решении классы получаются неравноправными.
> я не знаю, подразумевали ли вы максимальную скорость работы.
> если нет, то от static_cast'ов чрезвычайно легко избавиться, сделав чисто виртуальные методы вроде
Да, подразумевал, ведь и нежелание хранить указатель в publisher-е - это тоже оптимизация.
Использование виртуальных функций, кстати, решает ещё одну серьёзную проблему:
вдруг кто-то в конструкторе/деструкторе ArtLebedevDesign обратится к функции publisher и получит обращение к несоздавшемуся/удалённому классу (в вашем случае такое тоже может быть, ведь констуктор publisher вызывается до ( ... )
Reply
Согласен. Но тут это, ИМХО, оправдано, т.к. выполняется отношения ArtLebedev IS DesignStudio и ArtLebedev IS BookPublisher.
Это нам с вами надо определиться в чем цель измениний. Я подразумеваю, что идет процесс выделения функциональности в отдельный класс. Поэтому интерфейс тоже меняется. Собственно, может быть ради интерфейса это все и затевалось. Речь идет ведь как раз о ссылке на родительский класс, т.е. родительский класс по-прежнему выполняет часть работы.
Reply
Leave a comment