Implicit Interfaces

T

Tony

class Interface
{
public:
virtual void DoItNow()=0;
};

class A: public Interface
{
public:
void DoItNow(); // satisfies interface explicitly
};

class B
{
public:
void DoItNow(); // could satisfy interface implicitly
};

// Must wrap B to get a class to behave like Interface :(
//
class C: public Interface
{
B rep;
public:
void DoItNow(){ rep.DoItNow(); }
};

void some_func(Interface* obj)
{
obj->DoItNow();
}

void another_func()
{
A a; // IS explicitly an Interface
B b; // is NOT an explicit Interface
C c; // wraps a B to use it as an Interface
some_func(&a); // obviously OK
some_func(&b); // error! b is not derived from Interface
some_func(&c); // obviously OK
}

If the second call worked via implicit interfaces, the
wrapper class C could be eliminated. Am I describing
dynamic typing? Are Implicit Interfaces what template-
only "concepts" (proposed) are hinting at? I don't think
it's dynamic typing, becuase I'd want to know at compile
time whether an object satisfies an interface or not.
Templates consider type while interfaces consider behavior.
Do Implicit Interfaces add "the other half" of what's missing
to templates? Replace them?

Just thinking out loud above and below...

class Drawable
{
virtual void Draw()=0;
};

class Window
{
void Draw();
};

class Graphic
{
void Draw();
};

class BillyTheKid
{
void Draw();
};

Window, Graphic, BillyTheKid are all Drawables implicitly.
A Graphic is not a Window though because Window is not an
interface class (pure ABC). Sure, you'll get weird results if
you pass a BillyTheKid to a Canvas object, but is the concept
of Implicit Interfaces still something to be pursued?

Hmmm.... I'm talking about "aspects" kinda? Do we need all
these mechanisms: templates, template concepts, aspects,
dynamic typing, implicit interfaces... others? I guess I'm
wondering in a remote way if impicit interfaces solve or could
solve a lot of the problems the other ones do.

Well that's enough brainstorming for Xmas night (!).

Tony
 
K

kwikius

Tony wrote:

<...>



#include <iostream>
#ifdef __GXX_CONCEPTS__
//http://www.generic-programming.org/software/ConceptGCC/
auto concept Interface<typename T>{
void T::DoItNow();
};

#endif
//class Interface
//{
// public:
// virtual void DoItNow()=0;
//
//
//};

class A //: public Interface
{
public:
void DoItNow(){std::cout << "A DoItNow\n";} // satisfies
};

class B
{
public:
void DoItNow(){std::cout << "B DoItNow\n";} // could satisfy
};

// Must wrap B to get a class to behave like Interface :(
//
class C //: public Interface
{
B rep;
public:
void DoItNow(){ rep.DoItNow(); }
};

template <typename T>
#ifdef __GXX_CONCEPTS__
where Interface<T>
#endif
void some_func(T* obj)
{
obj->DoItNow();
}

void another_func()
{
A a; // IS explicitly an Interface
B b; // is NOT an explicit Interface
C c; // wraps a B to use it as an Interface
some_func(&a); // obviously OK
some_func(&b); // error! b is not derived from Interface
some_func(&c); // obviously OK
}

int main()
{
another_func();
}

//------------------------
regards
Andy Little
 
T

Tony

kwikius said:
Tony wrote:

<...>



#include <iostream>
#ifdef __GXX_CONCEPTS__
//http://www.generic-programming.org/software/ConceptGCC/
auto concept Interface<typename T>{
void T::DoItNow();
};

#endif
//class Interface
//{
// public:
// virtual void DoItNow()=0;
//
//
//};

class A //: public Interface
{
public:
void DoItNow(){std::cout << "A DoItNow\n";} // satisfies
};

class B
{
public:
void DoItNow(){std::cout << "B DoItNow\n";} // could satisfy
};

// Must wrap B to get a class to behave like Interface :(
//
class C //: public Interface
{
B rep;
public:
void DoItNow(){ rep.DoItNow(); }
};

template <typename T>
#ifdef __GXX_CONCEPTS__
where Interface<T>
#endif
void some_func(T* obj)
{
obj->DoItNow();
}

void another_func()
{
A a; // IS explicitly an Interface
B b; // is NOT an explicit Interface
C c; // wraps a B to use it as an Interface
some_func(&a); // obviously OK
some_func(&b); // error! b is not derived from Interface
some_func(&c); // obviously OK
}

int main()
{
another_func();
}

That doesn't answer any of the questions posed now does it.

Tony
 
K

kwikius

Tony said:
That doesn't answer any of the questions posed now does it.

It solves the coding problems.

As for the others... probably your best bet is a psychiatrist.

regards
Andy Little
 
?

=?iso-8859-1?q?Kirit_S=E6lensminde?=

Tony said:
class Interface
{
public:
virtual void DoItNow()=0;
};

class A: public Interface
{
public:
void DoItNow(); // satisfies interface explicitly
};

class B
{
public:
void DoItNow(); // could satisfy interface implicitly
};

// Must wrap B to get a class to behave like Interface :(
//
class C: public Interface
{
B rep;
public:
void DoItNow(){ rep.DoItNow(); }
};

void some_func(Interface* obj)
{
obj->DoItNow();
}

void another_func()
{
A a; // IS explicitly an Interface
B b; // is NOT an explicit Interface
C c; // wraps a B to use it as an Interface
some_func(&a); // obviously OK
some_func(&b); // error! b is not derived from Interface
some_func(&c); // obviously OK
}

If the second call worked via implicit interfaces, the
wrapper class C could be eliminated. Am I describing
dynamic typing? Are Implicit Interfaces what template-
only "concepts" (proposed) are hinting at? I don't think
it's dynamic typing, becuase I'd want to know at compile
time whether an object satisfies an interface or not.
Templates consider type while interfaces consider behavior.
Do Implicit Interfaces add "the other half" of what's missing
to templates? Replace them?

Just thinking out loud above and below...

class Drawable
{
virtual void Draw()=0;
};

class Window
{
void Draw();
};

class Graphic
{
void Draw();
};

class BillyTheKid
{
void Draw();
};

Window, Graphic, BillyTheKid are all Drawables implicitly.
A Graphic is not a Window though because Window is not an
interface class (pure ABC). Sure, you'll get weird results if
you pass a BillyTheKid to a Canvas object, but is the concept
of Implicit Interfaces still something to be pursued?

Hmmm.... I'm talking about "aspects" kinda? Do we need all
these mechanisms: templates, template concepts, aspects,
dynamic typing, implicit interfaces... others? I guess I'm
wondering in a remote way if impicit interfaces solve or could
solve a lot of the problems the other ones do.

What you're looking at is an application of operational polymorphism -
using a given operation on a type (these days often called ducktyping).
Your interface for some_func() however uses inclusional polymorphism,
that is that the super-class includes the type of the sub-classes.

Your version of some_func() doesn't work not because of the operation
on the type, but because you have specified the type of the parameter.
You can use operational polymorphism in C++ through templates, so this
should work for you:

template< typename I >
void some_func( I *obj ) {
obj->DoItNow();
}

Now some_func() is written in terms of the operations supported by the
type I and not by the class hierarchy of Interface.

In many places the two approaches are equivalent, but there are some
places where you are constrained by which you use. Normally this has to
do with how some_func() is to be used.

Traditionally OO design is heavily inclusional, but equating OO with
inclusional hierarchies is a mis-conception of what OO is about. I
think this isn't helped by Java which is a bit of an odd language in OO
terms - it is the only one I know that doesn't really support
operational polymorphism, which is the only type supported by most
other OO languages.

The STL is an example of OO design that uses mostly operational
polymorphism.


K
 
T

Tony

Kirit Sælensminde said:
What you're looking at is an application of operational polymorphism -

That sounds like changing an object's interface though, where the "plan"
was to make the compiler smart enough to recognize a class's interface
and procede if it matched the called-for interface. Hence "Implicit
Interfaces". (Yeah, it's a half-baked idea so far, but I'm trying to figure
out if there is something there worthy of pursuit perhaps especially
in regards to mix-ins/concepts/aspects).
using a given operation on a type (these days often called ducktyping).

Hmm. I've heard the term before. I'll have to google that.
Your interface for some_func() however uses inclusional polymorphism,
that is that the super-class includes the type of the sub-classes.

Your version of some_func() doesn't work not because of the operation
on the type, but because you have specified the type of the parameter.
You can use operational polymorphism in C++ through templates, so this
should work for you:

template< typename I >
void some_func( I *obj ) {
obj->DoItNow();
}

The goal was to avoid template machinery and look at interfaces as first
class citizens perhaps taking some responsibility away from the template
machinery.
Now some_func() is written in terms of the operations supported by the
type I and not by the class hierarchy of Interface.

The analysis requested though was why implicit interfaces won't work
or can't be made to work or how they can be made to work effectively.
Am I just asking to break type safety and that is the big issue? Well what
is a C++ type? A name? A public interface? "Pass by interface" comes
to mind as a possibility (akin to pass by value, address or reference).
In many places the two approaches are equivalent, but there are some
places where you are constrained by which you use. Normally this has to
do with how some_func() is to be used.

some_func() was not to be the focus at all. Rather, the non-Interface
derived class B and passing it around effectively.
Traditionally OO design is heavily inclusional, but equating OO with
inclusional hierarchies is a mis-conception of what OO is about. I
think this isn't helped by Java which is a bit of an odd language in OO
terms - it is the only one I know that doesn't really support
operational polymorphism, which is the only type supported by most
other OO languages.

The STL is an example of OO design that uses mostly operational
polymorphism.

Tony
 
?

=?iso-8859-1?q?Kirit_S=E6lensminde?=

Tony said:
That sounds like changing an object's interface though, where the "plan"
was to make the compiler smart enough to recognize a class's interface
and procede if it matched the called-for interface. Hence "Implicit
Interfaces". (Yeah, it's a half-baked idea so far, but I'm trying to figure
out if there is something there worthy of pursuit perhaps especially
in regards to mix-ins/concepts/aspects).


Hmm. I've heard the term before. I'll have to google that.

Please do. I think it will illuminate much of the rest of the
discussion. What seems sadly lacking is a general discussion of
different kinds of polymorphism and how they relate.
The goal was to avoid template machinery and look at interfaces as first
class citizens perhaps taking some responsibility away from the template
machinery.

I feel uncomfortable with the request to "avoid template machinery". I
see the template capability of C++ as a sane way of allowing
operational polymorphism within a strongly typed language. You can take
the view that Java does and only allow inclusional polymorphism, but
you are then cutting down on the ways you can express yourself in the
language. You can also take the view of Smalltalk/Javascript (nearly
every other OO language) which only allows operational polymorphism,
but then you then, in practice, disallow type checking before the
software is executed.

To my mind C++ has a very good balance between the two. I can use
specific hierarchies to package capabilities where that is the right
choice. I can use templates to provide a looser model where that works
better, and I can even use them to provide type inferencing where that
is most convenient.

The different parts of the language are there to support expression of
design ideals in different ways when you implement. If you cut off an
area of the syntax you necessarily limit your expressiveness in the
language.

I think the problem with what you propose is that you expect too much
from the compiler. How can it make it claim to type safety if you also
allow it to compromise it for any methods which happen to share the
same name?

Either you take the view that the type is defined as the top of a
hierarchy (the inclusional polymorphic view) and build your system on
this premise, or you take the operational polymorphic view that you
will support any type that understands a given set of messages. The
only way to express the latter in C++ is to use templates. You cannot
arbitrarily try to introduce operational polymorphism and at the same
time cut of the syntax that allows you to express it.

C++ is good in that it allows both forms of expression, but don't try
to confuse one form of expression with another. Please.
The analysis requested though was why implicit interfaces won't work
or can't be made to work or how they can be made to work effectively.
Am I just asking to break type safety and that is the big issue? Well what
is a C++ type? A name? A public interface? "Pass by interface" comes
to mind as a possibility (akin to pass by value, address or reference).

"What is a C++ type?" This is a good question which has many and
complex answers. It isn't as simple as in classic OO languages which
are generally type agnostic - so long as the object understands the
message everything should be fine.

C++ attempts to be a little stricter about it though. It wants to give
firm guarantees about the capabilities of the objects that your program
references. It has two mechanisms for this - inclusional and
operational. Both mechanisms have their places and for many uses our
software designs are put to either can be expressed as the other, but
not everywhere.

What this means in practice is that you cannot do without both class
hierarchies and templates if you want freedom to express yourself
freely as a programmer implementing a design.

You can pick and choose those parts of the language that you wish to
learn and use, but you cannot expect to then be able to express
yourself however you wish as well.
some_func() was not to be the focus at all. Rather, the non-Interface
derived class B and passing it around effectively.

I understand that, but it is a consequence of the type system of C++
together with the way that libraries are packaged that the use of
some_func() becomes a determinant on how the type of the argument needs
to be expressed.


K
 
T

Tony

Kirit Sælensminde said:
That sounds like changing an object's interface though, where the "plan"
was to make the compiler smart enough to recognize a class's interface
and procede if it matched the called-for interface. Hence "Implicit
Interfaces". (Yeah, it's a half-baked idea so far, but I'm trying to
figure
out if there is something there worthy of pursuit perhaps especially
in regards to mix-ins/concepts/aspects).


Hmm. I've heard the term before. I'll have to google that.

"Please do. I think it will illuminate much of the rest of the
discussion. "

On my "to do" list still.
What seems sadly lacking is a general discussion of
different kinds of polymorphism and how they relate.

I don't think so since the focus is on recognizing a class interface and
perhaps expanding the concept of what a type is in C++.
The goal was to avoid template machinery and look at interfaces as first
class citizens perhaps taking some responsibility away from the template
machinery.

"I feel uncomfortable with the request to "avoid template machinery". I
see the template capability of C++ as a sane way of allowing
operational polymorphism within a strongly typed language. You can take
the view that Java does and only allow inclusional polymorphism, but
you are then cutting down on the ways you can express yourself in the
language. You can also take the view of Smalltalk/Javascript (nearly
every other OO language) which only allows operational polymorphism,
but then you then, in practice, disallow type checking before the
software is executed.

To my mind C++ has a very good balance between the two. I can use
specific hierarchies to package capabilities where that is the right
choice. I can use templates to provide a looser model where that works
better, and I can even use them to provide type inferencing where that
is most convenient."

Well I was hoping for something cleaner and clearer to come out of
the implicit interface concept.

"The different parts of the language are there to support expression of
design ideals in different ways when you implement. If you cut off an
area of the syntax you necessarily limit your expressiveness in the
language."

And with all the "template tricks" possible, that's not a bad thing at
all IMO.

I think the problem with what you propose is that you expect too much
from the compiler."

Probably, but without comprehensive analysis and evolution/morphing
of the concept, I don't really know that. And I'm not the one to investigate
such low level stuff (compiler/language implentation).

"How can it make it claim to type safety if you also
allow it to compromise it for any methods which happen to share the
same name?"

I brought the relaxing of type safety issue up already. Even if the
concept was an evolved one, that may be too big of a pill to swallow.

"Either you take the view that the type is defined as the top of a
hierarchy (the inclusional polymorphic view) and build your system on
this premise,"

Am I doing that? I don't think so. I may want to compose an interface
"on the fly" as I program and want to "apply" it to an existing class
object without deriving a new class first. (Yeah, maybe it's too little
gain for too much pain, but I'm wondering what the implication or
potential is on things like concepts/aspects/dynamic typing).

" or you take the operational polymorphic view that you
will support any type that understands a given set of messages."

Not really. If a class doesn't have the appropriate interface (method
set defined by the interface called for), then it should be rejected at
compile time.

" The only way to express the latter in C++ is to use templates. You cannot
arbitrarily try to introduce operational polymorphism and at the same
time cut of the syntax that allows you to express it."

I don't think we're viewing it in the same way.

"C++ is good in that it allows both forms of expression, but don't try
to confuse one form of expression with another. Please."

Is he right?
The analysis requested though was why implicit interfaces won't work
or can't be made to work or how they can be made to work effectively.
Am I just asking to break type safety and that is the big issue? Well what
is a C++ type? A name? A public interface? "Pass by interface" comes
to mind as a possibility (akin to pass by value, address or reference).

""What is a C++ type?" This is a good question which has many and
complex answers. It isn't as simple as in classic OO languages which
are generally type agnostic - so long as the object understands the
message everything should be fine.

C++ attempts to be a little stricter about it though. It wants to give
firm guarantees about the capabilities of the objects that your program
references. It has two mechanisms for this - inclusional and
operational. Both mechanisms have their places and for many uses our
software designs are put to either can be expressed as the other, but
not everywhere.

What this means in practice is that you cannot do without both class
hierarchies and templates if you want freedom to express yourself
freely as a programmer implementing a design.

You can pick and choose those parts of the language that you wish to
learn and use, but you cannot expect to then be able to express
yourself however you wish as well."

Can you address the "pass by interface" concept in English please?
some_func() was not to be the focus at all. Rather, the non-Interface
derived class B and passing it around effectively.

"I understand that, but it is a consequence of the type system of C++
together with the way that libraries are packaged that the use of
some_func() becomes a determinant on how the type of the argument needs
to be expressed."

Yes but I wasn't trying to do something within the constraints of C++
as it is, but rather asking "what if?" and "what existing
mechanisms/rules/paradigms would have to change or be broken?" etc.

Tony
 
?

=?iso-8859-1?q?Kirit_S=E6lensminde?=

Tony said:
"Please do. I think it will illuminate much of the rest of the
discussion. "

On my "to do" list still.


I don't think so since the focus is on recognizing a class interface and
perhaps expanding the concept of what a type is in C++.


"I feel uncomfortable with the request to "avoid template machinery". I
see the template capability of C++ as a sane way of allowing
operational polymorphism within a strongly typed language. You can take
the view that Java does and only allow inclusional polymorphism, but
you are then cutting down on the ways you can express yourself in the
language. You can also take the view of Smalltalk/Javascript (nearly
every other OO language) which only allows operational polymorphism,
but then you then, in practice, disallow type checking before the
software is executed.

To my mind C++ has a very good balance between the two. I can use
specific hierarchies to package capabilities where that is the right
choice. I can use templates to provide a looser model where that works
better, and I can even use them to provide type inferencing where that
is most convenient."

Well I was hoping for something cleaner and clearer to come out of
the implicit interface concept.

"The different parts of the language are there to support expression of
design ideals in different ways when you implement. If you cut off an
area of the syntax you necessarily limit your expressiveness in the
language."

And with all the "template tricks" possible, that's not a bad thing at
all IMO.

I think the problem with what you propose is that you expect too much
from the compiler."

Probably, but without comprehensive analysis and evolution/morphing
of the concept, I don't really know that. And I'm not the one to investigate
such low level stuff (compiler/language implentation).

"How can it make it claim to type safety if you also
allow it to compromise it for any methods which happen to share the
same name?"

I brought the relaxing of type safety issue up already. Even if the
concept was an evolved one, that may be too big of a pill to swallow.

"Either you take the view that the type is defined as the top of a
hierarchy (the inclusional polymorphic view) and build your system on
this premise,"

Am I doing that? I don't think so. I may want to compose an interface
"on the fly" as I program and want to "apply" it to an existing class
object without deriving a new class first. (Yeah, maybe it's too little
gain for too much pain, but I'm wondering what the implication or
potential is on things like concepts/aspects/dynamic typing).

" or you take the operational polymorphic view that you
will support any type that understands a given set of messages."

Not really. If a class doesn't have the appropriate interface (method
set defined by the interface called for), then it should be rejected at
compile time.

" The only way to express the latter in C++ is to use templates. You cannot
arbitrarily try to introduce operational polymorphism and at the same
time cut of the syntax that allows you to express it."

I don't think we're viewing it in the same way.

"C++ is good in that it allows both forms of expression, but don't try
to confuse one form of expression with another. Please."

Is he right?


""What is a C++ type?" This is a good question which has many and
complex answers. It isn't as simple as in classic OO languages which
are generally type agnostic - so long as the object understands the
message everything should be fine.

C++ attempts to be a little stricter about it though. It wants to give
firm guarantees about the capabilities of the objects that your program
references. It has two mechanisms for this - inclusional and
operational. Both mechanisms have their places and for many uses our
software designs are put to either can be expressed as the other, but
not everywhere.

What this means in practice is that you cannot do without both class
hierarchies and templates if you want freedom to express yourself
freely as a programmer implementing a design.

You can pick and choose those parts of the language that you wish to
learn and use, but you cannot expect to then be able to express
yourself however you wish as well."

Can you address the "pass by interface" concept in English please?


"I understand that, but it is a consequence of the type system of C++
together with the way that libraries are packaged that the use of
some_func() becomes a determinant on how the type of the argument needs
to be expressed."

Yes but I wasn't trying to do something within the constraints of C++
as it is, but rather asking "what if?" and "what existing
mechanisms/rules/paradigms would have to change or be broken?" etc.

In order to do what you want you'd have to completely change the type
system in C++. The way to do what you want within the existing type
system is to use a templated some_func(). To do it without templates
would mean removing the inclusional polymorphism from the language.
It's really no more complex than that.

I suggest that you try your ideas in some other OO languages and you'll
see what happens. Smalltalk will allow you to try a language which
doesn't have inclusional polymorphism so your idea will work directly
in that language. Javascript is an OO language that also doesn't have
inheritance. Java is a language that doesn't have operational
polymorphism.

If you try your idea out in these different languages you may better
understand why C++'s type system is as it is.


K
 
T

Tony

kwikius said:
Java programmer!

regards
Andy Little

I resent that implication. You've taking insult to a whole new level
now. At least _I_ wasn't being ludicrous! :p

Tony
 
T

Tony

What you're looking at is an application of operational polymorphism -
using a given operation on a type (these days often called ducktyping).

I don't see any reason to call "interfaces" duck-anything. Yeah, I looked it
up a little and apparently they're talking about interfaces and dynamic
binding concepts. Fine. Is their some kind of resistence to evolving the
"programming with/to interfaces" concept? Perhaps because it rains on the
template parade?

Sure C++ has the concept of "type" but just like categories have
subcategories, what would be so wrong about some aspects/concepts/
dynamic typing/implicit interface thing that was in between "static typing
every time all the time" and dynamic typing?

The examples I gave indeed were like: "it's a duck, go ahead and use it
like one". I'm really asking if there is a simply elegant solution for
something that is lacking in the existing constructs and paradigms. And
apparently all the stuff going on with aspects/concepts etc. says it's more
than just a casual need (not that I personally made any good arguments
for it though).

I can guarantee that I'll not use anything that extends the template
machinery
any more. If it's not something that can pretty much be done as simple
text replacement-style "automation", well that's the only way I will ever
(knock on wood) use templates. (</soapbox>).

What I see: C++ knows about class names and a class name is the concept
of "type". Seems pretty limiting, but probably easy to implement (and I'm
all for keeping compiler complexity to a minimum). But the interface
paradigm/concept is just to compelling to not pursue it. Yeah, it probably
affects the implementation completely, but that's not to say it would
necessarily be difficult or complex to implement. Just that it would
change or maybe break things. If this "little thing" proves to be very
compelling, and C++ can't handle it because it has "baggage" (backward
compatibility constraints), it could really age C++ and put it in
"maintenance only" mode/existence. Of course I'm just talking very
abstractly. But I really think there is a lot of untapped potential in the
interface concept. Of course I just use this stuff rather than build it (but
it's not like I follow the "recipe"-style of C++ programming either).

Well I have to go and read some papers someone referred me to (or at
least skim them).

Tony
 
K

kwikius

Tony said:
I resent that implication. You've taking insult to a whole new level
now. At least _I_ wasn't being ludicrous! :p

Tony

Sorry man.. I think I went too far with that last one.

regards
Andy Little
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top