Проблема
Скажем, я пытаюсь смоделировать сотовый телефон как комбинацию обычного телефона и PDA. Это - вид сценария множественного наследования (сотовый телефон является телефоном, и это - PDA). Так как 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 }
}
Класс CellPhone
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 для добавления этого типа генерации кода? upvote это, если я сделал? В противном случае, какие возражения Вы имеете?
Править
Все, кажется, говорят то же самое: Почему я просто не делаю _phone
и _pda
в общественные собственности? Мое возражение на это состоит в том, что это нарушает "принцип наименьшего количества знания". Клиент моего CellPhone
класс должен просто сделать вещи, которые делает сотовый телефон, ему не придется иметь дело с выяснением, которое функции Phone
функции и которые являются Pda
функции. Это создает дополнительные зависимости и делает функции интерфейса CellPhone менее очевидными.
Кроме того, не фокусируйтесь только на этом примере. Что, если я писал адаптер? Это могло бы содержать несколько интерфейсных участников, которые являются просто передачами, но это могло бы также содержать некоторых уникальных участников с уникальной реализацией. Я полагаю, что существует много случаев, где код передачи является хорошей вещью, мне просто не нравится писать это.
Да, вы можете генерировать методы, используя Brilliant vs Add-In, Resharper
Выберите «, генерируют методы делегирования ». Меню поколения (ALT-вставка с схемой ярлыков по умолчанию).
Если у вас есть класс, который реализует интерфейс, содержащий поле, которое реализует один и тот же интерфейс, R # даст вам возможность генерировать код пропускания. Это может работать с любым количеством интерфейсов.
Я видел это предложение раньше (не обязательно на переполнении стека). Это было некоторое время назад. Я считаю, что автор создал проблему CONNECT, хотя я не знаю его статус.
Предлагаемый синтаксис был одним из следующих:
public class CellPhone : IPhone, IPda
{
private readonly IPhone _phone implements IPhone;
private readonly IPda _pda : IPda;
// ...
}
Интересный вопрос. Может ли класс мобильного телефона действительно полагаться на реализацию методов iPhone, предоставляемых существующим бетонным классом iPhone? Или это более вероятно, что мобильный телефон понадобится какой-то пользовательский код, поддерживающий эти методы?
Глядя на ваш код (хотя я не знаю много о ваших требованиях) заставляет меня хотеть написать что-то подобное:
public class CellPhone
{
private Phone _phone;
private Pda _pda;
public CellPhone(Phone phone, Pda pda)
{
_phone = phone;
_pda = pda;
}
public IPhone getPhone()
{
return _phone;
}
public IPda getPda()
{
return _pda;
}
public void MakeCall(string contactName) {
int phoneNumber = _pda.LookUpContactPhoneNumber(contactName);
_phone.MakeCall(phoneNumber);
}
}
Вопрос 2:
Мне не очень нравится автоматически сгенерированный код. Даже если машина генерирует ее - и без ошибок - вы все равно нести ответственность за поддержание его. Эти методы кажутся так много шума.