Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating pass-through code when "preferring composition over inheritance"

Tags:

Problem

Let's say I'm trying to model a cell phone as a combination of a regular phone and a PDA. It's sort of a multiple inheritance scenario (a cell phone is a phone, and it is a PDA). Since C# doesn't support multiple inheritance, this pretty much calls for some kind composition. Plus, let's say that I have other reasons to favor composition anyway.

The thing I always wonder: Are there any tools that will generate all the inevitable pass-through code automatically?

Let me flesh out my example with some actual code:

Interfaces:

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();
}

Implementations:

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 }
}

The CellPhone class

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();
    }
}

Writing the CellPhone class is tedious and error-prone:

All this class really does is act as a conduit for the Phone and Pda classes. There is really no reason human effort should be required to type out all these pass-through statements (like _phone.MakeCall(phoneNumber);). It's just exposing the public interface of a couple member fields.

Questions

  1. Is there a tool (preferably free :)) that will save me from the error-prone tedium of writing pass-through methods? I'm aware that I can automatically generate the stubs using VS, but this only gets me half the way there.

  2. Can you rate the feasibility and desirability of such a feature? Would it be worth putting in a suggestion to Microsoft to add this type of code generation? Would you upvote it if I did? If not, what objections do you have?

Edit

Everyone seems to be saying the same thing: Why don't I just make _phone and _pda into public properties? My objection to this is that it violates the "principle of least knowledge". The client of my CellPhone class should just do the things a cell phone does, it shouldn't have to deal with figuring out which features are Phone features and which are Pda features. This creates additional dependencies and makes the features of the CellPhone interface less obvious.

Also, don't focus just on this example. What if I were writing an adapter? It might contain several interface members that are just pass-throughs, but it might also contain some unique members with unique implementation. I believe there are many cases where pass-through code is a good thing, I just don't like writing it.

like image 495
devuxer Avatar asked Jan 27 '10 21:01

devuxer


2 Answers

Yes, you can generate the methods using the brilliant VS add-in, ReSharper

Choose the "generate delegating methods" option from the code-generation menu (Alt-Insert with the default shortcut scheme).

Where you have a class that implements an interface, containing a field that implements the same interface, R# will give you an option to generate the pass-through code. It can work with any number of interfaces, too.

like image 64
Mark Simpson Avatar answered Sep 19 '22 15:09

Mark Simpson


I have seen this suggestion before (not necessarily on Stack Overflow). It was a while ago. I believe the author created a Connect issue, though I don't know its status.

The proposed syntax was one of the following:

public class CellPhone : IPhone, IPda
{
    private readonly IPhone _phone implements IPhone;
    private readonly IPda _pda : IPda;

    // ...
}
like image 29
Bryan Watts Avatar answered Sep 20 '22 15:09

Bryan Watts