3

Admittedly, this is a homework problem but I have tried to figure it out on my own. Just want to make sure I get it correct. So far, the only design pattern I believe to be correct would be the Adapter design pattern. I could implement an Adapter class to publicly inherit from class C and privately from class D and instantiate the following:

D *d = new Adapter();
d->foo();

However, would this qualify as subtyping?

The problem:

Suppose we have the following class:

class C { /* ... */ public: int foo (); int bar (); };

Also suppose that this class is only available in compiled form, i.e., that it cannot be modified. Now we want to add an alternative implementation that only has a method foo() but that does not have a method bar() and does not inherit the data members from class C. I.e., this new class D would have the structure

class D /* ... */ { public: int foo (); };

but it cannot inherit from class C. Suppose we want to maintain a list of objects that can be from either classes C or D. Explain how you can design this list data structure, traverse the list, and call foo() on each element, such that the appropriate method C::foo() or D::foo() is executed depending on the type of the object. Do not use either if-statements or structural subtyping.

  • Interfaces are your friend here. – Greg Burghardt Oct 21 '16 at 21:55
  • Use composition if inheritance is forbidden. – Robert Harvey Oct 21 '16 at 22:19
  • So for composition, I could essentialy have Class D take a Class C as argument and access it inside of D using something like objC.foo(); ? – TacoB0t Oct 21 '16 at 23:10
  • Yes. Or you could simply new up a class C inside of D. – Robert Harvey Oct 21 '16 at 23:17
  • What language is this in? Object systems very wildly between languages. For example, there's a very clean and trivial solution in OCaml, but I'm not sure that's what you're looking for :) – gardenhead Oct 22 '16 at 2:32
3

Your problem states that D shall not inherit from C and that it doesn't inherit C's variables. It furthermore states that is is an alternative implementation.

I therefore think the question is not about making D an adapter (e.g. D*d=new adapter()). You have to consider that C and D are given classes that are independent but just share a common function in the interface.

Now the only design pattern that you could use here is the adapter pattern. There are two main way to implement this pattern:

  • use of private inheritance to the adapted class and offer the target interface.
  • use of composition, containing or pointing to an object of the adapted class and offering the interface.

In your problem, it is explicitly prohibited to use "structural subtyping". So forget about inheritance approach for the adapter. Use composition instead. As you are not allowed to use if you can't query the type, nor could you use two pointers (one to C and one to D) and ignore one if it's null.

So the only way is to use an abstract adapter class with two implementations (but none of them inherit from D or C):

class Adapter {
public:  virtual int foo()=0; 
         virtual ~Adapter() {}
};
class Adpater_C : public Adapter {   // could also be templatized 
public:  int foo() override { return c.foo() }; 
private: C c;  // instead of the object, could be a pointer to another existing object.
}; 
class Adpater_D : public Adapter {
public:  int foo() override { return d.foo() }; 
private: D d;  
}; 

In your list you could then store pointers to Adapter (or better unique_ptr<Adapter>) and execute blindly the polymorphic foo() for every item.

  • Why did you make Adapter an abstract class instead of an interface? That is the only difference between the solution you proposed and the one I did. Other than the possibility that Adapter class will have some properties later on, is there any other reason for using abstract class instead of interface? – Vladimir Stokic Oct 24 '16 at 7:08
  • @VladimirStokic because OP uses c++ which doesn't know about interfaces; he needs to explicitely tell which functions are polymorphic. I tried also to explain the reason that lead to that design and why it's better suited than the other usual c++ implementation of the adapter that is based on multiple inhertance (private inheritance of each adapter specialisation from the original classes) – Christophe Oct 24 '16 at 7:44
  • @Cristophe Yes, I neglected the programming language that you used. My bad. – Vladimir Stokic Oct 24 '16 at 13:36
  • @VladimirStokic, Cristophe: Java is also allowed in answers, which does support interfaces. – outis Oct 31 '16 at 9:05
  • @outis of course : the question is language neutral :-) therefore it's normal to have different answers tailored to mainstream type systems (mi & inteefaces). And there's still room for an answer based on an oo laguage with more dynamic typing ;-) – Christophe Oct 31 '16 at 9:29
2

First of all, inheritance is not an option, especially if the methods of the class C are not virtual to begin with. You can do something like this (the language used is C#, but the approach works in C++ too, obviously):

public class C
{
    public void foo()
    {
    }

    public void bar()
    {
    }
}

public class D
{
    public void foo()
    {
    }
}

public interface FooExecutor
{
    void foo();
}

public class CExecutor : FooExecutor
{
    C cMember;

    public CExecutor (C c)
    {
        cMember = c;
    }

    public void foo()
    {
         cMember.foo();
    }
}

public class DExecutor : FooExecutor
{
    D dMember;

    public DExecutor (D d)
    {
        dMember = d;
    }

    public void foo()
    {
         dMember.foo();
    }
}

And then you could create your list like this (of course, this is grossly simplifying and shortening the code):

List<FooExecutor> myList = new List<FooExecutor>();
myList.Add(new CExecutor(new C());
myList.Add(new DExecutor(new D());

foreach (FooExecutor f in myList)
{
    f.foo();
}

And there you go... This is, basically, an Adapter pattern, and without using if statements, this is the only way I can think of solving the problem you posted.

2

The pattern is composition.

Let's say we introduce interface A with method foo.

Since we own class D we can trivially add implements A to it.

Then we define a composite class E implements A, with a field of type C and a constructor that take an object of type C and an implementation of foo which just calls foo on the member object of type C.

Now you only need to wrap all C class objects in this E class delegator before putting them into the List<A>.

0

Your question presupposes that some design pattern exists that will solve it. While the answers posted here are or are related to the Adapter pattern and do solve your problem, you shouldn't limit your thinking to just design patterns, especially if you are just starting out in software design.

  • Yes, thank you for that! Initially I was going to implement templates but when told there was a design pattern that could solve this, I was curious about the design pattern's implementation and simply learning more about that and just got carried away with design patterns. – TacoB0t Oct 24 '16 at 3:57
  • Doesn't this sounds more like a comment than a real answer ? – Christophe Oct 29 '16 at 23:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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