У меня есть класс верхнего уровня, который создает экземпляры подмодулей, используя композицию. Пользователь знает, что в высшем классе будут эти подмодули. Стоит ли делать объекты подмодуля публичными членами, чтобы пользователь мог напрямую вызывать их функции?
Альтернатива, по-видимому, заключается в том, чтобы обернуть их вызовы функций, которые защищают подмодули от обнародования, но не имеют никаких преимуществ инкапсуляции, поскольку пользователю все равно нужно указать подмодуль.
Перед вами дом класса высший уровень с подмодульной кухней и санузлом.
// Public member objects
class Kitchen {
public:
void turn_on_tap();
int compute_area();
};
class Bathroom {
public:
void turn_on_tap();
int compute_area();
};
class House {
public:
Kitchen kitchen;
Bathroom bathroom;
int compute_area() { return kitchen.compute_area() + bathroom.compute_area(); }
};
//User code:
House house;
house.kitchen.turn_on_tap();
house.bathroom.turn_on_tap();
house.compute_area() // OK
house.bathroom.compute_area(); // may not want user to be able to do this
// Private member objects
class House {
Kitchen kitchen;
Bathroom bathroom;
public:
void turn_on_kitchen_tap() { kitchen.turn_on_tap(); }
void turn_on_bathroom_tap() { bathroom.turn_on_tap(); }
int compute_area() { return kitchen.compute_area() + bathroom.compute_area(); }
};
//User code:
House house;
house.turn_on_kitchen_tap();
house.turn_on_bathroom_tap();
house.compute_area();
Я предпочитаю синтаксис первого, но это означает, что объекты-члены должны быть общедоступными.
Второй подход кажется утомительным из-за дополнительных функций, которые мне приходится писать для переноса базовых вызовов функций. И я теряю красивое точечное иерархическое разыменование, потому что пользователь знает (и должен знать) о лежащей в основе иерархии.
РЕДАКТИРОВАТЬ: Но если я сделаю их общедоступными, я открою доступ к другим публичным функциям на кухне и в ванной, о которых я не обязательно хочу, чтобы пользователь знал. Так что тогда мне, возможно, придется сделать их приватными и использовать «друг», что становится немного уродливым.
В приведенный выше код добавлена функция calculate_area().