Задача
Допустим, я пытаюсь смоделировать сотовый телефон как комбинацию обычного телефона и КПК. Это своего рода сценарий множественного наследования (сотовый телефон - это телефон , а - это КПК). Поскольку C # не поддерживает множественное наследование, это в значительной степени требует некоторой композиции. Кроме того, скажем, у меня есть другие причины отдать предпочтение композиции.
Мне всегда интересно: есть ли инструменты, которые автоматически сгенерируют весь неизбежный сквозной код?
Позвольте мне привести в пример мой реальный код:
Интерфейсы:
public interface IPhone
{
public void MakeCall(int phoneNumber);
public void AnswerCall();
public void HangUp();
}
public interface IPda
{
public void SendEmail(string[] recipientList, string subject, string message);
public int LookUpContactPhoneNumber(string contactName);
public void SyncWithComputer();
}
Реализация:
public class Phone : IPhone
{
public void MakeCall(int phoneNumber) { // implementation }
public void AnswerCall() { // implementation }
public void HangUp() { // implementation }
}
public class Pda : IPda
{
public void SendEmail(string[] recipientList, string subject, string message) { // implementation }
public int LookUpContactPhoneNumber(string contactName) { // implementation }
public void SyncWithComputer() { // implementation }
}
Класс сотового телефона
public class CellPhone : IPhone, IPda
{
private IPhone _phone;
private IPda _pda;
public CellPhone(IPhone phone, IPda pda)
{
_phone = phone;
_pda = pda;
}
public void MakeCall(int phoneNumber)
{
_phone.MakeCall(phoneNumber);
}
public void AnswerCall()
{
_phone.AnswerCall();
}
public void HangUp()
{
_phone.HangUp();
}
public void SendEmail(string[] recipientList, string subject, string message)
{
_pda.SendEmail(recipientList, subject, message);
}
public int LookUpContactPhoneNumber(string contactName)
{
return _pda.LookUpContactPhoneNumber(contactName);
}
public void SyncWithComputer()
{
_pda.SyncWithComputer();
}
}
Написание класса CellPhone утомительно и подвержено ошибкам:
Все, что на самом деле делает этот класс, является проводником для классов Phone
и Pda
. На самом деле нет никаких причин, по которым человеческие усилия должны требоваться для ввода всех этих сквозных операторов (например, _phone.MakeCall(phoneNumber);
). Он просто открывает доступ к общедоступному интерфейсу пары полей-членов.
Вопросы
Есть ли инструмент (желательно бесплатный :)), который избавит меня от склонной к ошибкам написания сквозных методов? Я знаю, что могу автоматически генерировать заглушки, используя VS, но это только дает мне половину пути.
Можете ли вы оценить целесообразность и желательность такой функции? Стоит ли предлагать Microsoft добавить этот тип генерации кода? Вы бы проголосовали, если бы я это сделал? Если нет, то какие у вас возражения?
Редактировать
Кажется, все говорят одно и то же: почему я просто не превращаю _phone
и _pda
в общедоступные объекты? Я возражаю против этого, что это нарушает «принцип наименьшего знания». Клиент моего класса CellPhone
должен просто делать то, что делает сотовый телефон, ему не нужно разбираться, какие функции являются Phone
функциями, а какие Pda
. Это создает дополнительные зависимости и делает функции интерфейса CellPhone менее очевидными.
Кроме того, не зацикливайтесь только на этом примере. Что если бы я писал адаптер? Он может содержать несколько элементов интерфейса, которые являются просто сквозными, но он также может содержать несколько уникальных членов с уникальной реализацией. Я считаю, что во многих случаях транзитный код - это хорошая вещь , я просто не люблю его писать.