February 22, 2004
In article <c1aqle$q79$1@digitaldaemon.com>, Ant says...
>
>In article <c1aobj$m94$1@digitaldaemon.com>, Brad Anderson says...
>>
>>John Reimer and I *are* those poor folks, and it's becoming a problem.  I still don't know a work-around to get the compiler to stop complaining.  Should we change the abstracts and interfaces to plain old classes, inherit the "partial-implementation" and be disciplined about which members we implement? Or should we try your throwing exceptions idea?
>>
>>BA
>
>neither.
>
>You should convince Walter that abstract classes
>don't need a full implementation of the interface.
>
>Ant

BTW do you remember I warned about this problem a couple of months
ago when we started talking about SWT? (couldn't find the post)
I didn't realize it is by design and not a bug...

Ant


February 22, 2004
Kris wrote:
>
> I have several issues with this, but to put it in a nutshell: *partial
> implementation (via an abstract class) can be, and in larger projects is
> often used as, a gracious mechanism for solving real-world problems*

Perhaps I'm missing something, but is there some reason the interfaces can't be broken up?  Here's an example:

class CanRunAndJump -> class CanRun -> interface JumperRunner

From what you've said, this may be a case where I'd like to implement the running methods in CanRun and leave the jumping methods for the CanRunAndJump class.  Is this right?  If so, I don't agree that partial implementation is a good thing.  It would make more logical sense to do this:

class CanRunAndJump -> class CanRun -> interface RunnerAndJumper
class CanRunAndJump -> interface Jumper

Or is the goal to provide paritally implemented base classes and force the user to implement the remaining methods?  In this case, why not do this:

interface RunnerAndJumper {
    void run();
    void jump();
}

class CanRun : RunnerAndJumper {
    void run() {}
    void jump()
    in {
        assert( 0 );
        // this function must be overridden in a base class
    }
    {}
}

February 22, 2004
Inline:


"Sean Kelly" <sean@ffwd.cx> wrote in message news:c1b8jd$1ipi$1@digitaldaemon.com...
>  From what you've said, this may be a case where I'd like to implement
> the running methods in CanRun and leave the jumping methods for the
> CanRunAndJump class.  Is this right?  If so, I don't agree that partial
> implementation is a good thing.  It would make more logical sense to do
> this:
>
> class CanRunAndJump -> class CanRun -> interface RunnerAndJumper class CanRunAndJump -> interface Jumper

Did you mean "interface Runner" (not "interface RunnerAndJumper") in the first line? If so I agree, but that example is not the issue.

> Or is the goal to provide paritally implemented base classes and force the user to implement the remaining methods?  In this case, why not do
this:
>
> interface RunnerAndJumper {
>      void run();
>      void jump();
> }
>
> class CanRun : RunnerAndJumper {
>      void run() {}
>      void jump()
>      in {
>          assert( 0 );
>          // this function must be overridden in a base class
>      }
>      {}
> }


It's this second example that I have a beef with Sean;

(1) we perhaps ought to change it as follows because it should *always* fail
(this is what I shivered at in the initial post).:

class CanRun : RunnerAndJumper
{
      void run() {}
      void jump()
           {
           // this function must be overridden in a base class
           assert( 0 );
           }
 }

(2) how does an IDE tell the programmer what specifically should be overridden? It can't. And you can't rely on access to the source code for such classes, although you should have the public interface (but that still tells you squat). More importantly, there should be a compile-time error (versus runtime) about instantiation or usage of such an implementation. This is simply a ticking bomb -- not cool at all.

(3) such 'declarative' interfaces are great for plugable systems, where multiple people or vendors are involved. For example, you might expose a specific kind of device-driver via such an interface, but the concrete implementations built by each hardware vendor would at minimum implement only their specialized variation [jump(), in this case] whereas run() could be common to all/most implementations within an abstract base-class representing the interface. When one constructs *multiple* layers like this, it's very useful (and very robust) to have default implementations of some interface methods whilst at the same time explicitly stating:

"you must implement this particular area" for any given level -- it's a contractual obligation, made at design-time rather than at implementation-time.

Of course, one can implement using your example #2; but any such system will become fragile over time.

(4) as others pointed out, writing these little glue-wrappers is error-prone, messy, and tedious. That's not good for long-term maintenance.

I'm not suggesting that D must support this <g> ... rather I'm trying to discover and understand the rationale for not supporting partial-implementation (and certainly in the absence of mixins).

In other words: I need to know the most robust way to handle this in D, before I start writing serious quantities of related code.

cheers;






February 23, 2004
Kris wrote:
>
> (3) such 'declarative' interfaces are great for plugable systems, where
> multiple people or vendors are involved. For example, you might expose a
> specific kind of device-driver via such an interface, but the concrete
> implementations built by each hardware vendor would at minimum implement
> only their specialized variation [jump(), in this case] whereas run() could
> be common to all/most implementations within an abstract base-class
> representing the interface. When one constructs *multiple* layers like this,
> it's very useful (and very robust) to have default implementations of some
> interface methods whilst at the same time explicitly stating:
> 
> "you must implement this particular area" for any given level -- it's a
> contractual obligation, made at design-time rather than at
> implementation-time.

I know it's another kludge, but what about packaging a set of test functions with the library?  I think it would be more robust to offer a way to verify that a derived class not only implements such functions but does so correctly.  I'd perhaps combine this with pre and post conditions for every function to make use even more obvious.

I personally am not averse to expecting users to read and follow the documentation, but then I come from a C++ background where this may be more of a requirement than with other languages.  Especially in combination with DBC I think the need for precise documentation is critical.

As for why partial implementations aren't supported by D... I have no idea.  I tend to avoid such programming methods myself but I can understand how they are useful in certain contexts.


Sean

February 23, 2004
Without a compelling reason, I completely agree with your assessment, and consider interfaces in D broken. :-(

It shows how much OO programming I've been doing in D - he he - as I was unaware of this.

(FWIW, I've been doing stacks in several other languages of late. =P )

Percy The Proceduralist

"Kris" <someidiot@earthlink.net> wrote in message news:c19p93$21f7$1@digitaldaemon.com...
> Much to his credit, Walter has often noted specific reasoning for the presence or absence of some particular D language-choice. Perhaps someone will please be good enough to clarify one that (superficially) doesn't
seem
> to have received much attention:  according to the spec, "All interface functions must be defined in a class that inherits from that interface".
The
> compiler says so also.
>
> I have several issues with this, but to put it in a nutshell: *partial implementation (via an abstract class) can be, and in larger projects is often used as, a gracious mechanism for solving real-world problems*
>
> <rant>
> Ok. Certainly one can work around this by implementing fake members in
said
> "abstract" base-class, and throw an exception in each of those that should *actually* be implemented by a subclass ... but that is serious kludge, especially since instantiation of said abstract class would be perfectly legal at *compile-time*. That's not cool. It's also far less than helpful
to
> a smart IDE that could guide a user in what they should truly be implementing. Should such an IDE resort to "hints" in the (non-existent) documentation? These kind of things are important vis-a-vis acceptance.
>
> Here's something else: what D needs to gain wide acceptance is good set of libraries. The easiest way to get those quickly is to port existing proven/accepted/cool/elegant ones. One particular type of D library that seems rather popular is that of the GUI manager/widget library. How many
of
> those are there? Hmmmm, four or more current projects? Far more popular
than
> any other type of library, because it's a necessity for a large swathe of
> software development. The SWT port is such a project, and it truly has the
> potential to make D shine. How easy do you think it's gonna' be for those
> poor folks to (mechanically) port SWT over to D without support for
> partial-implementation and/or abstract-classes?
> </rant>
>
> Porting great libraries is a *truly* real-world problem -- if we can make that easier then D has a better chance of acceptance in such an
environment.
>
> So, finally, why doesn't D support
partial-implementation/abstract-classes?
> I'm sure there's probably a good reason why it's not already there; but
what
> is that reason?
>
> - Kris
>
>
>
>



February 23, 2004
"Andy Friesen" <andy@ikagames.com> wrote in message news:c1ar58$qvs$1@digitaldaemon.com...
> Brad Anderson wrote:
>
> > John Reimer and I *are* those poor folks, and it's becoming a problem. I still don't know a work-around to get the compiler to stop complaining.  Should we change the abstracts and interfaces to plain old classes, inherit the "partial-implementation" and be disciplined about which members we implement? Or should we try your throwing exceptions
idea?
>
> I'd throw an InternalError or somesuch until we can get Walter to cave in and fix it. (or at least tell us why it can't/shouldn't be fixed)

I guess you've no choice.

But having runtime error checks for something that is pre-compile-time, i.e. design time, is just evil.



February 23, 2004
"Sean Kelly" <sean@ffwd.cx> wrote in message news:c1b8jd$1ipi$1@digitaldaemon.com...
> Kris wrote:
> >
> > I have several issues with this, but to put it in a nutshell: *partial implementation (via an abstract class) can be, and in larger projects is often used as, a gracious mechanism for solving real-world problems*
>
> Perhaps I'm missing something, but is there some reason the interfaces can't be broken up?  Here's an example:
>
> class CanRunAndJump -> class CanRun -> interface JumperRunner
>
>  From what you've said, this may be a case where I'd like to implement
> the running methods in CanRun and leave the jumping methods for the
> CanRunAndJump class.  Is this right?  If so, I don't agree that partial
> implementation is a good thing.  It would make more logical sense to do
> this:
>
> class CanRunAndJump -> class CanRun -> interface RunnerAndJumper class CanRunAndJump -> interface Jumper
>
> Or is the goal to provide paritally implemented base classes and force the user to implement the remaining methods?  In this case, why not do
this:
>
> interface RunnerAndJumper {
>      void run();
>      void jump();
> }
>
> class CanRun : RunnerAndJumper {
>      void run() {}
>      void jump()
>      in {
>          assert( 0 );
>          // this function must be overridden in a base class
>      }
>      {}
> }

Because now someone can create an instance of CanRun, which is wrong because it is notionally abstract, even if not practically so.






February 25, 2004
I think I found a really convoluted way to get around this issue:

interface Wumpus
{
    void wumpus();
}

class Bar : Wumpus
{
    void wumpus(){}; // we're forced to implement
                                // the entire interface
}

class Foo : Bar
{
    abstract override void wumpus(); // aha! it works!
}

main()
{
    Wumpus wumpus = new Foo();  // error: abstract class
}

The 'partial' implementation is in class Bar, but it needs to be wrapped with class Foo to ensure interface method wumpus() cannot be invoked for Bar (because it's not intended to be implemented there in the first place!). That is wacky, highly error-prone, and truly hideous.

Since we can write really ugly code to sidestep this compiler 'policy', can we just have the real thing instead? Pretty please <g>

- Kris


"Kris" <someidiot@earthlink.net> wrote in message news:c19p93$21f7$1@digitaldaemon.com...
> Much to his credit, Walter has often noted specific reasoning for the presence or absence of some particular D language-choice. Perhaps someone will please be good enough to clarify one that (superficially) doesn't
seem
> to have received much attention:  according to the spec, "All interface functions must be defined in a class that inherits from that interface".
The
> compiler says so also.
>
> I have several issues with this, but to put it in a nutshell: *partial implementation (via an abstract class) can be, and in larger projects is often used as, a gracious mechanism for solving real-world problems*
>
> <rant>
> Ok. Certainly one can work around this by implementing fake members in
said
> "abstract" base-class, and throw an exception in each of those that should *actually* be implemented by a subclass ... but that is serious kludge, especially since instantiation of said abstract class would be perfectly legal at *compile-time*. That's not cool. It's also far less than helpful
to
> a smart IDE that could guide a user in what they should truly be implementing. Should such an IDE resort to "hints" in the (non-existent) documentation? These kind of things are important vis-a-vis acceptance.
>
> Here's something else: what D needs to gain wide acceptance is good set of libraries. The easiest way to get those quickly is to port existing proven/accepted/cool/elegant ones. One particular type of D library that seems rather popular is that of the GUI manager/widget library. How many
of
> those are there? Hmmmm, four or more current projects? Far more popular
than
> any other type of library, because it's a necessity for a large swathe of
> software development. The SWT port is such a project, and it truly has the
> potential to make D shine. How easy do you think it's gonna' be for those
> poor folks to (mechanically) port SWT over to D without support for
> partial-implementation and/or abstract-classes?
> </rant>
>
> Porting great libraries is a *truly* real-world problem -- if we can make that easier then D has a better chance of acceptance in such an
environment.
>
> So, finally, why doesn't D support
partial-implementation/abstract-classes?
> I'm sure there's probably a good reason why it's not already there; but
what
> is that reason?
>
> - Kris
>
>
>
>


1 2
Next ›   Last »