Jump to page: 1 2 3
Thread overview
[BUG] yet another interface related issue
Apr 07, 2004
Kris
Apr 07, 2004
Ivan Senji
Apr 07, 2004
Kris
Apr 07, 2004
Ben Hinkle
Apr 07, 2004
Kris
Apr 07, 2004
Ant
Apr 07, 2004
Kris
Apr 07, 2004
C
Apr 08, 2004
Phill
Apr 09, 2004
John Reimer
Apr 07, 2004
Ben Hinkle
Apr 07, 2004
John Reimer
Apr 07, 2004
Kris
Apr 07, 2004
John Reimer
Apr 07, 2004
Kris
Apr 08, 2004
Russ Lewis
Apr 09, 2004
Kris
Apr 07, 2004
C
Apr 07, 2004
Walter
Apr 07, 2004
Kris
Apr 08, 2004
Phill
April 07, 2004
I'm sure many of you are sick to death of hearing about Interface related flaws and bugs: personally, I'm thoroughly fed up of running into them. This one is another doozy ...

OK; so we have a extensible Tokenizer subsystem. It scans input for delimited content and places the results in a Token. Here's a stripped-down version of the participants:

class Token
{
    private char[] value;

    void setValue (char[] value)
    {
       this.value = value;
    }
}

class Tokenizer
{
    abstract bool next (Token token);

    // other base-class stuff here
}

class LineTokenizer : Tokenizer
{
    bool next (Token token)
    {
    // do some stuff

    // set Token content
    token.setValue (....);
    }
}

There are a variety of Tokenizer derivatives that handle different scanning flavours. We can specialize with a SpaceTokenizer, CommaTokenizer, RegexTokenizer, and so on. They all operate upon the basic Token class.

Now, we wish to introduce a *slightly* more sophisticated Token derivative called CookieToken:

class CookieToken : Token
{
    private char[] name;

    void setName (char[] name)
    {
        this.name = name;
    }
}

... and we want to pass it to a CookieTokenizer:

class CookieTokenizer : Tokenizer
{
    bool next (CookieToken token)
    {
    // do some stuff

    // set Token content
    token.setValue (....);
    token.setName (...);
    }
}

Note how the abstract method next() should accept a CookieToken rather than
the basic Token?

So, the compiler says (and I quote)  "No wayyy pal. CookieTokenizer is now one o' them abstract-classes cos' yer method signatures cannae be matched".

OK. Fair enough, Mr Compiler. This is where the power of Interfaces is typically brought to bear: one would simply "virtualize" the basic Token class with an IToken interface.

"All ABOARD!".   Here we go now ...

// define interface
interface IToken
{
   void setValue (char[]);
}

// specify that our Token implements the IToken interface
class Token : IToken
{
   void setValue (char[]);
}

// update Tokenizer base-class with the Interface
class Tokenizer
{
    abstract bool next (IToken token);

    // other base-class stuff here
}

// update LineTokenizer with the Interface
class LineTokenizer : Tokenizer
{
    bool next (IToken token)
    {
    // do some stuff

    // set Token content
    token.setValue (....);
    }
}

So far so good.  Now we should be able to pass our CookieToken to the next() method because it is an *instance* of the IToken Interface. This concept  is a fundamental of contractual-specification support that an OO Interface exposes:

class CookieTokenizer : Tokenizer
{
    bool next (CookieToken token)
    {
    // do some stuff

    // set Token content
    token.setValue (....);
    token.setName (...);
    }
}

Hey Presto!

Whoops! Compiler says "Oan yer bike pally! Ahh don't care a wee flying *&%# if yer CookieToken is an IToken instance or no!"

Well, what can one say to that?  Actually, I can think of a few choice phrases ...

This is Interfaces 101, people. It doesn't even pass the sniff test. One might confidently state that the method-matching algorithm has absolutely no concept of Interfaces.

You might think one could use a base-class instead right? Well, unfortunately, that didn't work in the first instance (before the Interface attempt). Apparently, D simply does not grok the concept of passing derived objects as an argument via a base-class. Let alone Interfaces. Can anyone say "polymorphic meltdown" ?

Sigh. Double Sigh.  Any ideas? Suggestions? Resolutions? Should I just give up?

- Kris


April 07, 2004
I'm not shure that i know exactly what the problem is,but can you not do
this:
class CookieTokenizer : Tokenizer
{
    bool next (IToken token)
    {
    // do some stuff

    // set Token content
    token.setValue (....);
    token.setName (...);
    }
}

Then CookieTokenizer can take as an argument CookieToken because it
implements IToken
but it can't be cast to CookieToken to use it's specific properties?

My plan was for these days to convert a parser i am writing in D to a
version thet doesnt just take an argument
of type char[][] but it can take an argument of type ILexicalElement,
then the user implements ILexicalElement in his class and can,
call my parser but what happens when i want to return to the user
ILexicalElement (for example i return the one that coused a parsing error)
and the user cant cast it back to his (MyLexElement) type to get some
extra information?

If i understand the problems with D interfaces i will have to wait before i convert my project to interfaces-version :(


"Kris" <someidiot@earthlink.dot.dot.dot.net> wrote in message news:c505g4$1n6f$1@digitaldaemon.com...
> I'm sure many of you are sick to death of hearing about Interface related flaws and bugs: personally, I'm thoroughly fed up of running into them.
This
> one is another doozy ...
>
> OK; so we have a extensible Tokenizer subsystem. It scans input for delimited content and places the results in a Token. Here's a
stripped-down
> version of the participants:
>
> class Token
> {
>     private char[] value;
>
>     void setValue (char[] value)
>     {
>        this.value = value;
>     }
> }
>
> class Tokenizer
> {
>     abstract bool next (Token token);
>
>     // other base-class stuff here
> }
>
> class LineTokenizer : Tokenizer
> {
>     bool next (Token token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     }
> }
>
> There are a variety of Tokenizer derivatives that handle different
scanning
> flavours. We can specialize with a SpaceTokenizer, CommaTokenizer, RegexTokenizer, and so on. They all operate upon the basic Token class.
>
> Now, we wish to introduce a *slightly* more sophisticated Token derivative called CookieToken:
>
> class CookieToken : Token
> {
>     private char[] name;
>
>     void setName (char[] name)
>     {
>         this.name = name;
>     }
> }
>
> ... and we want to pass it to a CookieTokenizer:
>
> class CookieTokenizer : Tokenizer
> {
>     bool next (CookieToken token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     token.setName (...);
>     }
> }
>
> Note how the abstract method next() should accept a CookieToken rather
than
> the basic Token?
>
> So, the compiler says (and I quote)  "No wayyy pal. CookieTokenizer is now one o' them abstract-classes cos' yer method signatures cannae be
matched".
>
> OK. Fair enough, Mr Compiler. This is where the power of Interfaces is typically brought to bear: one would simply "virtualize" the basic Token class with an IToken interface.
>
> "All ABOARD!".   Here we go now ...
>
> // define interface
> interface IToken
> {
>    void setValue (char[]);
> }
>
> // specify that our Token implements the IToken interface
> class Token : IToken
> {
>    void setValue (char[]);
> }
>
> // update Tokenizer base-class with the Interface
> class Tokenizer
> {
>     abstract bool next (IToken token);
>
>     // other base-class stuff here
> }
>
> // update LineTokenizer with the Interface
> class LineTokenizer : Tokenizer
> {
>     bool next (IToken token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     }
> }
>
> So far so good.  Now we should be able to pass our CookieToken to the
next()
> method because it is an *instance* of the IToken Interface. This concept
is
> a fundamental of contractual-specification support that an OO Interface exposes:
>
> class CookieTokenizer : Tokenizer
> {
>     bool next (CookieToken token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     token.setName (...);
>     }
> }
>
> Hey Presto!
>
> Whoops! Compiler says "Oan yer bike pally! Ahh don't care a wee flying
*&%#
> if yer CookieToken is an IToken instance or no!"
>
> Well, what can one say to that?  Actually, I can think of a few choice phrases ...
>
> This is Interfaces 101, people. It doesn't even pass the sniff test. One might confidently state that the method-matching algorithm has absolutely
no
> concept of Interfaces.
>
> You might think one could use a base-class instead right? Well, unfortunately, that didn't work in the first instance (before the
Interface
> attempt). Apparently, D simply does not grok the concept of passing
derived
> objects as an argument via a base-class. Let alone Interfaces. Can anyone say "polymorphic meltdown" ?
>
> Sigh. Double Sigh.  Any ideas? Suggestions? Resolutions? Should I just
give
> up?
>
> - Kris
>
>


April 07, 2004
"Ivan Senji" <ivan.senji@public.srce.hr> wrote in message news:c508u1$1sbm$1@digitaldaemon.com...
> Then CookieTokenizer can take as an argument CookieToken because it
> implements IToken
> but it can't be cast to CookieToken to use it's specific properties?

Yes, one could use an upcast inside the next() method (that's just what I'm
doing to keep momentum going). But there's at least five problems with that
approach Ivan:

1) it totally abandons the inutuitive, expressive, and bug-eliminating approach that Interfaces were designed to help one avoid. That is, D does not support some of the most basic Interface fundamentals (and arguably some OO fundamentals).

2) It's counter-intuitive. One of the stated goals for D was, and is, "ease of use". The required use of upcasts to handle even this trivial design is so far off base ... I don't even know where to begin.

3) Cast should be avoided as much as possible, so as the compiler can tell you when you're doing something wrong. This is especially true for non-expert users. Again, Interfaces were designed to alleviate this.

4) the upcast would be a dynamic_cast. That's not a trivial piece of code to execute (it has a loop), so there are performance implications that could easily be avoided with the correct semantic support.

5) And perhaps worst of all: If, as you suggest, one were to upcast the IToken argument, the D compiler will silently emit bogus code into your executable such that it will deliberately cause an access-violation at runtime (in place of the upcast). According to recent public record, this is per design. The compiler is not expected to issue an error. Again, I just don't know what to say about that.

> and the user cant cast it back to his (MyLexElement) type to get some
> extra information?

As it stands, you cannot cast() an interface back to a concrete object. The compiler emits code to cause ... well, we know what it does.

You can revert to an arcane "decoration" approach, whereby your interface (and Object) exposes a method with this pattern:

Object  toObject() {return this;}

Once you get the Interface converted to a real Object, you can then upcast it, using the slow dynamic_cast. Once again, this is not exactly what I'd refer to as "ease of use".

Oh well; perhaps some good will come out of this farce :-(

- Kris


April 07, 2004
> // update LineTokenizer with the Interface
> class LineTokenizer : Tokenizer
> {
>     bool next (IToken token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     }
> }
>
> So far so good.  Now we should be able to pass our CookieToken to the
next()
> method because it is an *instance* of the IToken Interface. This concept
is
> a fundamental of contractual-specification support that an OO Interface exposes:
>
> class CookieTokenizer : Tokenizer
> {
>     bool next (CookieToken token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     token.setName (...);
>     }
> }

Were you expecting the
 bool next(CookitToken token)
to override
 bool next(IToken token)
If so I don't agree it should override. It is a very different signature.
Overload, sure, but not override.
Then again, maybe I don't understand your question.

-Ben


April 07, 2004
> Sigh. Double Sigh.  Any ideas? Suggestions? Resolutions? Should I just give
> up?

Patience.  All good things take time.  You've made a good case and I think Walter realizes something must be done.

C

On Tue, 6 Apr 2004 22:09:00 -0800, Kris <someidiot@earthlink.dot.dot.dot.net> wrote:

> I'm sure many of you are sick to death of hearing about Interface related
> flaws and bugs: personally, I'm thoroughly fed up of running into them. This
> one is another doozy ...
>
> OK; so we have a extensible Tokenizer subsystem. It scans input for
> delimited content and places the results in a Token. Here's a stripped-down
> version of the participants:
>
> class Token
> {
>     private char[] value;
>
>     void setValue (char[] value)
>     {
>        this.value = value;
>     }
> }
>
> class Tokenizer
> {
>     abstract bool next (Token token);
>
>     // other base-class stuff here
> }
>
> class LineTokenizer : Tokenizer
> {
>     bool next (Token token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     }
> }
>
> There are a variety of Tokenizer derivatives that handle different scanning
> flavours. We can specialize with a SpaceTokenizer, CommaTokenizer,
> RegexTokenizer, and so on. They all operate upon the basic Token class.
>
> Now, we wish to introduce a *slightly* more sophisticated Token derivative
> called CookieToken:
>
> class CookieToken : Token
> {
>     private char[] name;
>
>     void setName (char[] name)
>     {
>         this.name = name;
>     }
> }
>
> ... and we want to pass it to a CookieTokenizer:
>
> class CookieTokenizer : Tokenizer
> {
>     bool next (CookieToken token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     token.setName (...);
>     }
> }
>
> Note how the abstract method next() should accept a CookieToken rather than
> the basic Token?
>
> So, the compiler says (and I quote)  "No wayyy pal. CookieTokenizer is now
> one o' them abstract-classes cos' yer method signatures cannae be matched".
>
> OK. Fair enough, Mr Compiler. This is where the power of Interfaces is
> typically brought to bear: one would simply "virtualize" the basic Token
> class with an IToken interface.
>
> "All ABOARD!".   Here we go now ...
>
> // define interface
> interface IToken
> {
>    void setValue (char[]);
> }
>
> // specify that our Token implements the IToken interface
> class Token : IToken
> {
>    void setValue (char[]);
> }
>
> // update Tokenizer base-class with the Interface
> class Tokenizer
> {
>     abstract bool next (IToken token);
>
>     // other base-class stuff here
> }
>
> // update LineTokenizer with the Interface
> class LineTokenizer : Tokenizer
> {
>     bool next (IToken token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     }
> }
>
> So far so good.  Now we should be able to pass our CookieToken to the next()
> method because it is an *instance* of the IToken Interface. This concept  is
> a fundamental of contractual-specification support that an OO Interface
> exposes:
>
> class CookieTokenizer : Tokenizer
> {
>     bool next (CookieToken token)
>     {
>     // do some stuff
>
>     // set Token content
>     token.setValue (....);
>     token.setName (...);
>     }
> }
>
> Hey Presto!
>
> Whoops! Compiler says "Oan yer bike pally! Ahh don't care a wee flying *&%#
> if yer CookieToken is an IToken instance or no!"
>
> Well, what can one say to that?  Actually, I can think of a few choice
> phrases ...
>
> This is Interfaces 101, people. It doesn't even pass the sniff test. One
> might confidently state that the method-matching algorithm has absolutely no
> concept of Interfaces.
>
> You might think one could use a base-class instead right? Well,
> unfortunately, that didn't work in the first instance (before the Interface
> attempt). Apparently, D simply does not grok the concept of passing derived
> objects as an argument via a base-class. Let alone Interfaces. Can anyone
> say "polymorphic meltdown" ?
>
> Sigh. Double Sigh.  Any ideas? Suggestions? Resolutions? Should I just give
> up?
>
> - Kris
>
>



-- 
D Newsgroup.
April 07, 2004
Having to perform an upcast for such a trivial design is, in my opinion, a failure at the language level, Ben; particularly so when cast() on an Interface deliberately barfs at runtime.

And I suppose that post is really not a question, but a rant. Perhaps I'm Overloaded with frustration on what appears to be a zero level of commitment on Walter's part to even consider fixing the Interface travesty. Rather, the few responses (to posts by myself and others) have been laced with denial.

Trying hard to get these three projects completed (in support of D, I might add), yet there's precious little in the way of "OK, let's take a serious look at these issues".  It really seems as though every turn in the road vis-a-vis Interfaces is met with a metaphorical stonewall.

On Reflection, I sound pissed-off.  I should probably just back away;

- Kris


"Ben Hinkle" <bhinkle4@juno.com> wrote in message news:c50vlp$2ves$1@digitaldaemon.com...
> > // update LineTokenizer with the Interface
> > class LineTokenizer : Tokenizer
> > {
> >     bool next (IToken token)
> >     {
> >     // do some stuff
> >
> >     // set Token content
> >     token.setValue (....);
> >     }
> > }
> >
> > So far so good.  Now we should be able to pass our CookieToken to the
> next()
> > method because it is an *instance* of the IToken Interface. This concept
> is
> > a fundamental of contractual-specification support that an OO Interface exposes:
> >
> > class CookieTokenizer : Tokenizer
> > {
> >     bool next (CookieToken token)
> >     {
> >     // do some stuff
> >
> >     // set Token content
> >     token.setValue (....);
> >     token.setName (...);
> >     }
> > }
>
> Were you expecting the
>  bool next(CookitToken token)
> to override
>  bool next(IToken token)
> If so I don't agree it should override. It is a very different signature.
> Overload, sure, but not override.
> Then again, maybe I don't understand your question.
>
> -Ben
>
>


April 07, 2004
In article <c51k9i$tqm$1@digitaldaemon.com>, Kris says...
>
>Having to perform an upcast for such a trivial design is, in my opinion, a failure at the language level, Ben; particularly so when cast() on an Interface deliberately barfs at runtime.
>
>And I suppose that post is really not a question, but a rant. Perhaps I'm Overloaded with frustration on what appears to be a zero level of commitment on Walter's part to even consider fixing the Interface travesty.

Walter tends to say things only once.
but sometimes he says a different thing
on the change log of the new release!

He might even responde directly to you and all we others will be left on the dark...

Ant


April 07, 2004
Thanks, Antonio.

I'll be sure to let you know (personally) if it's the latter <g>


"Ant" <Ant_member@pathlink.com> wrote in message news:c51m6l$10j9$1@digitaldaemon.com...
> In article <c51k9i$tqm$1@digitaldaemon.com>, Kris says...
> >
> >Having to perform an upcast for such a trivial design is, in my opinion,
a
> >failure at the language level, Ben; particularly so when cast() on an Interface deliberately barfs at runtime.
> >
> >And I suppose that post is really not a question, but a rant. Perhaps I'm Overloaded with frustration on what appears to be a zero level of
commitment
> >on Walter's part to even consider fixing the Interface travesty.
>
> Walter tends to say things only once.
> but sometimes he says a different thing
> on the change log of the new release!
>
> He might even responde directly to you and all we others will be left on the dark...
>
> Ant
>
>


April 07, 2004
Yea hes notoriously non-commital , but the changes usually find there way in there.  (Could you let me know also pls ? , preciate it :) )

C

On Wed, 7 Apr 2004 12:06:34 -0800, Kris <someidiot@earthlink.dot.dot.dot.net> wrote:

> Thanks, Antonio.
>
> I'll be sure to let you know (personally) if it's the latter <g>
>
>
> "Ant" <Ant_member@pathlink.com> wrote in message
> news:c51m6l$10j9$1@digitaldaemon.com...
>> In article <c51k9i$tqm$1@digitaldaemon.com>, Kris says...
>> >
>> >Having to perform an upcast for such a trivial design is, in my 
>> opinion,
> a
>> >failure at the language level, Ben; particularly so when cast() on an
>> >Interface deliberately barfs at runtime.
>> >
>> >And I suppose that post is really not a question, but a rant. Perhaps 
>> I'm
>> >Overloaded with frustration on what appears to be a zero level of
> commitment
>> >on Walter's part to even consider fixing the Interface travesty.
>>
>> Walter tends to say things only once.
>> but sometimes he says a different thing
>> on the change log of the new release!
>>
>> He might even responde directly to you and all we others
>> will be left on the dark...
>>
>> Ant
>>
>>
>
>



-- 
D Newsgroup.
April 07, 2004
About the whole upcasting thing...
implementing a "Castable" interface isn't too bad:

version = castable;

interface Castable {
  Object object();
}

// any interface that wants to be castable should extend Castable
interface IFoo : Castable {
  void foo();
}

// sample class implementing a castable interface
class Foo: IFoo {
  void foo() { print();} // IFoo
  Object object(){ return this; } // Castable
}

// sample function that takes a castable interface
void bar(IFoo x)
{
  Foo y;
  version(castable) {
    y = cast(Foo)x.object; // "cast" using .object
  } else {
    y = cast(Foo)x; // regular casts return null
  }
  y.print();
}

int
main()
{
  bar(new Foo());
  return 0;
}


« First   ‹ Prev
1 2 3