Connecting Tech Pros Worldwide Forums | Help | Site Map

How to solve this gracefully?

Alex
Guest
 
Posts: n/a
#1: Jul 23 '05
Hi, I have a problem involving some design issue.
I have two unrelated (that is, they do not derive from the same base)
classes:
ClassA
ClassB

Both have a quite similar interface, so they can be use interchangeably,
that is:

ptr = new ClassA;
ptr->f1();
ptr->f2();

To replace it with ClassB, all I need is changing the first line:

ptr = new ClassB;
ptr->f1();
ptr->f2();

(As I mentioned before, almost all the interface is identical)

This is OK when doing by hand. But I want to provide an option so a user can
toggle between both classes.
Problem is that as both classes are unrelated, I can't use a base pointer to
make instantiation..
So the most simple way I found is creating a proxy-like class, which
determines and forces the interface to be used:

class Iface {
public:
void f1();
void f2();
};

So doing:
class NewA : public ClassA, public Iface {
public:
void f1() { ClassA::f1(); }
void f2() { ClassA::f2(); }
};

and similarly
class NewB : public ClassB, public Iface {
public:
void f1() { ClassB::f1(); }
void f2() { ClassB::f2(); }
};

the I'm able to code:

Iface* ptr = new NewA;
or
Iface* ptr = new NewB;

and use them interchangeably.

Problem is -as you might have noticed- that the code to define the classes
is repetitive..

Is there a better way to solve this, and make it more elegant?

Note that in the future, I'll use ClassC with a not so similar interface. So
I find in this case the solution to be OK,
but in this specific case, maybe there's a shorter way?

Thanks.



Heinz Ozwirk
Guest
 
Posts: n/a
#2: Jul 23 '05

re: How to solve this gracefully?


"Alex" <no@domain.com> schrieb im Newsbeitrag
news:da0gl9$5re$1@nsnmpen3-gest.nuria.telefonica-data.net...[color=blue]
> Hi, I have a problem involving some design issue.
> I have two unrelated (that is, they do not derive from the same base)
> classes:
> ClassA
> ClassB
>
> Both have a quite similar interface, so they can be use interchangeably,
> that is:
>
> ptr = new ClassA;
> ptr->f1();
> ptr->f2();
>
> To replace it with ClassB, all I need is changing the first line:
>
> ptr = new ClassB;
> ptr->f1();
> ptr->f2();
>
> (As I mentioned before, almost all the interface is identical)
>
> This is OK when doing by hand. But I want to provide an option so a user
> can toggle between both classes.
> Problem is that as both classes are unrelated, I can't use a base pointer
> to make instantiation..
> So the most simple way I found is creating a proxy-like class, which
> determines and forces the interface to be used:
>
> class Iface {
> public:
> void f1();
> void f2();
> };[/color]

All member functions of the interface should be virtual (and probably pure).
You should also add a virtual d'tor.
[color=blue]
> So doing:
> class NewA : public ClassA, public Iface {
> public:
> void f1() { ClassA::f1(); }
> void f2() { ClassA::f2(); }
> };
>
> and similarly
> class NewB : public ClassB, public Iface {
> public:
> void f1() { ClassB::f1(); }
> void f2() { ClassB::f2(); }
> };[/color]

You can use templates to save those repetitions:

template <class Z>
class NewZ: public Z, public Iface
{
public:
void f1() { Z::f1(); }
void f2() { Z::f2(); }
};

typedef NewZ<A> NewA;
typedef NewZ<B> NewB;

HTH
Heinz


Alex
Guest
 
Posts: n/a
#3: Jul 23 '05

re: How to solve this gracefully?


>> This is OK when doing by hand. But I want to provide an option so a user[color=blue][color=green]
>> can toggle between both classes.
>> Problem is that as both classes are unrelated, I can't use a base pointer
>> to make instantiation..
>> So the most simple way I found is creating a proxy-like class, which
>> determines and forces the interface to be used:
>>
>> class Iface {
>> public:
>> void f1();
>> void f2();
>> };[/color]
>
> All member functions of the interface should be virtual (and probably
> pure). You should also add a virtual d'tor.[/color]

Yeah, you're right!
[color=blue][color=green]
>> So doing:
>> class NewA : public ClassA, public Iface {
>> public:
>> void f1() { ClassA::f1(); }
>> void f2() { ClassA::f2(); }
>> };
>>
>> and similarly
>> class NewB : public ClassB, public Iface {
>> public:
>> void f1() { ClassB::f1(); }
>> void f2() { ClassB::f2(); }
>> };[/color]
>
> You can use templates to save those repetitions:
>
> template <class Z>
> class NewZ: public Z, public Iface
> {
> public:
> void f1() { Z::f1(); }
> void f2() { Z::f2(); }
> };
>
> typedef NewZ<A> NewA;
> typedef NewZ<B> NewB;[/color]

This is great, thanks. So the method I use seems to be the best way to solve
this?
Can this be considered like a proxy pattern approach?


Heinz Ozwirk
Guest
 
Posts: n/a
#4: Jul 23 '05

re: How to solve this gracefully?


"Alex" <no@domain.com> schrieb im Newsbeitrag
news:da8r9q$gkb$1@nsnmpen3-gest.nuria.telefonica-data.net...
[color=blue]
> This is great, thanks. So the method I use seems to be the best way to
> solve this?[/color]

I would never call a method to do something "the best one". There is always
the possibility, that someone comes up with a better solution. There are
only good solutions and bad solutions, and as far as I understood the
problem you wanted to solve, I wouldn't call your solution a bad one. Your
first approach had the problem that you had to manually create many wrappers
for all your types, but that has been simlyfied using a template and letting
the compiler to do the dirty work.

HTH
Heinz


Closed Thread