C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Using templates to require interface

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Tim Conkling
Guest





PostPosted: Wed Sep 28, 2005 5:40 pm    Post subject: Using templates to require interface Reply with quote



Templates seem to facilitate a method of requiring that particular
interfaces be implemented in classes without requiring that those
classes extend a particular parent class.

For example:

I have two pure-virtual classes, FooInterface1 and FooInterface2. They
both have a foo() function, but they don't implement any common
interface that declares this foo() function.

I can create a new template class:

template <class T>
class BarClass
{
void bar()
{
((T*) this)->foo();
}
};

I can now create subclasses of FooInterface1 and FooInterface2 (and any
other classes that declare the foo() function) that also inherit from
BarClass:

class FooChild1 :
public FooInterface1,
public BarClass<FooChild1>
{...};

class FooChild2 :
public FooInterface2,
public BarClass<FooChild2>
{...};

In this way I can use BarClass anywhere that I need to have a class
that defines a foo() function, without requiring that the class inherit
from some particular superclass.


I'm (thinking about) doing this in an application I'm writing to avoid
a problem where I have a class "IClickable" that declares a function
"intersects()". Certain classes implementing IClickable will already
have an intersects() function from an ancestor class, while others will
not. If I make IClickable a template class, as above, I can let classes
implementing IClickable choose how they define the intersects()
function.

Is this bad design, or a bad implementation of a design pattern that
could be implemented more elegantly? Are there potential problems with
the design that I haven't considered?

Thanks,
Tim


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Greg Herlihy
Guest





PostPosted: Sat Oct 01, 2005 1:56 am    Post subject: Re: Using templates to require interface Reply with quote



Tim Conkling wrote:
Quote:
Templates seem to facilitate a method of requiring that particular
interfaces be implemented in classes without requiring that those
classes extend a particular parent class.

For example:

I have two pure-virtual classes, FooInterface1 and FooInterface2. They
both have a foo() function, but they don't implement any common
interface that declares this foo() function.

I can create a new template class:

template <class T
class BarClass
{
void bar()
{
((T*) this)->foo();
}
};

I can now create subclasses of FooInterface1 and FooInterface2 (and any
other classes that declare the foo() function) that also inherit from
BarClass:

class FooChild1 :
public FooInterface1,
public BarClass<FooChild1
{...};

class FooChild2 :
public FooInterface2,
public BarClass {...};

In this way I can use BarClass anywhere that I need to have a class
that defines a foo() function, without requiring that the class inherit
from some particular superclass.


I'm (thinking about) doing this in an application I'm writing to avoid
a problem where I have a class "IClickable" that declares a function
"intersects()". Certain classes implementing IClickable will already
have an intersects() function from an ancestor class, while others will
not. If I make IClickable a template class, as above, I can let classes
implementing IClickable choose how they define the intersects()
function.

Is this bad design, or a bad implementation of a design pattern that
could be implemented more elegantly? Are there potential problems with
the design that I haven't considered?

This kind of design most closely resembles the "adapter" pattern in
which various otherwise unrelated components all implement a common
interface, thereby allowing a client to use them more or less
interchangeably. I think this kind of shared interface mechanism is a
very useful, though often overlooked technique in C++. The lack of
formal support for this pattern in the language may explain why this
pattern is not more common in C++ programs. Other computer languages do
have explicit support for sharing interfaces without inheritance:
"protocols" and "categories" in Objective-C or "interfaces" in Java,
for example. Of course one could also argue that C++ does not need to
offer formal support for shared interfaces, since it is possible to
achieve much the same effect through the use of templates. Because C++
templates support type-dependent names, a template can in effect
require that its parameterized type implement a set of names - in
short, that it implements an interface.

Without formal support for shared interfaces in C++, each
implementation that uses them must address this issue on its own: how
do C++ clients know what routines comprise the shared interface? How is
the interface both advertised and documented? Here, simpler is probably
better. I think a straightforward solution is to have the template
class do no more than simply forward calls to the underlying
implementation. Although it may be tempting to add special purpose code
to the template class, doing so can risks inconsistentencies across
implmentations. Unlike an inherited interface which imposes a set of
constraints upon a subclass automatically, a shared interface is
"voluntarily" adopted. The specific implementation is based on one each
class's interpretation of the shared interface. Furthermore, the class
has no interface in a base class to fall back on. Implementing an
interface consistently is therefore a greater challenge when that
interface is shared among classes instead of inherited.

To give an idea how a shared interface might look in practice, let's
consider an interface for clickable objects. First, we'll declare the
shared interface as an abstract class:

class IClickable
{
public:
void DoClick() = 0;
void DoDoubleClick() = 0;
...
};

Now let's say that an unrelated class, Button, decides to adhere to the
IClickable interface without inheriting from it - or any other class:

class Button
{
public:
...
void DoClick();
void DoDoubleClick();
};

and lastly the template that will bind Button to the IClickable
interface:

template class Clickable: public Clickable
{
public:
Clickable(T *inClickable) :
mClickable(inClickable)
{
}

virtual void DoClick()
{
mClickable->DoClick();
}

virtual void DoDoubleClick()
{
mClickable-> DoDoubleClick();
}
private:
T *mClickable;
};

With this infrastructure, Button can be used anywhere an IClickable
would be accepted even though Button does not inherit from any other
class. In fact, Button's cooperation is not strictly necessary, as long
it implements methods with the expected names. This separation between
the implementation and the interface is one primary benefits of this
pattern. A change to an inherited interface can ripple throughout a
class hierarchy often requiring related changes in other classes'
interfaces. In contrast, the Clickable template can alter its interface
at will and nothing in Button needs to be changed.

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.