Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've recently read several articles about the advantages of the composition over inheritance. Their authors said that you can always replace inheritance with composition (to be precise, they say they don't know such situations where it can't be done). However, I can't think how to do this in the following case:

abstract class Reader
{
    public Int32 ReadSum()
    {
        return this.ReadValue() + this.ReadValue();
    }

    public Int32 ReadSub()
    {
        return this.ReadValue() - this.ReadValue();
    }

    public Int32 ReadMul()
    {
        return this.ReadValue() * this.ReadValue();
    }

    public Int32 ReadDiv()
    {
        return this.ReadValue() / this.ReadValue();
    }

    public abstract Int32 ReadValue();
}

class RandomSource: Reader
{
    public Int32 ReadValue()
    {
        return Math.RandomInt32();
    }
}

class UserSource: Reader
{
    public Int32 ReadValue()
    {
        return Console.ReadInt32();
    }
}

Is this at all possible?

share|improve this question
    
Worth noting that both the inheritance based solution in the question and the composition based solution in the two answers can be described as design patterns: Template Method and Strategy respectively. –  Aviv Cohn Aug 5 at 12:40

2 Answers 2

up vote 10 down vote accepted

This example is a bit contrived but here's one way.

You seem to have things going on here - operations and reading. The reading should be done by Reader and the operations can be performed by a different class.

class ReadOperations {

     private Reader reader;

     public Int32 ReadSum()
     {
       return reader.ReadValue() + reader.ReadValue();
     }

     public Int32 ReadSub()
     { 
        return reader.ReadValue() - reader.ReadValue();
     }

     public Int32 ReadMul()
     {
       return reader.ReadValue() * reader.ReadValue();
     }

     public Int32 ReadDiv()
     {
        return reader.ReadValue() / reader.ReadValue();
     }

}

interface Reader {

  public Int32 ReadValue();
}

class RandomSource: Reader
{
    public Int32 ReadValue()
    {
        return Math.RandomInt32();
    }
}

class UserSource: Reader
{
    public Int32 ReadValue()
    {
        return Console.ReadInt32();
    }
}

Depending on what you want there are other ways to do this.

You should have to find a way to inject the reader - probably with a constructor.

Disclaimer - for practical purposes you don't "need" to use composition, but doing so is extensible and you should use it whenever you think your program can evolve in a certain direction.

In this case, if you think your operations will evolve independently from the way you "read".

share|improve this answer
    
+1 Your example is equivalent to mine; I only chose a function because I find it simpler. An interface may help document intent, but it’s extensible, so the intent may be diluted over time if you carelessly add methods. –  Jon Purdy Aug 5 at 6:41
    
@JonPurdy You are right - your answer seems equivalent although I don't know C# :-). I didn't see your answer when I posted mine. –  Chip Aug 5 at 8:59
    
Yeah, you posted while I was still writing my answer, though I didn’t read it until after I’d posted. –  Jon Purdy Aug 5 at 9:16
    
@Chip Thank you both for good examples! –  Menzoda Aug 5 at 10:18

Sure, for example you can pass the reading behaviours into the Reader class from outside:

class Reader
{
    private Func<Int32> read;

    public Reader(Func<Int32> read)
    {
        this.read = read;
    }

    public Int32 ReadSum()
    {
        return read() + read();
    }

    …

}

Then you say something like new Reader(() => Math.RandomInt32()) to construct the equivalent of a RandomSource, or new Reader(() => Console.ReadInt32()) for a UserSource.

In general, replacing inheritance with composition leads to fewer nominal types such as UserSource, because their behaviour emerges from the composition of simpler components. You can of course make “constructor functions” like NewUserSource() for the sake of convenience.

(I’m not up on my C#, so bear with me if I’ve gotten some minor language details wrong here.)

share|improve this answer
    
Thank for good example! –  Menzoda Aug 5 at 10:19
    
+1 although personally I would prefer a new explicit interface such as IReaderStrategy rather than a Func<> delegate, for clarity –  Alex G Aug 5 at 11:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.