July 25, 2004
Walter wrote:
> "Kris" <someidiot@earthlink.dot.dot.dot.net> wrote in message
> news:cdu57d$1474$1@digitaldaemon.com...
>>I implore you to please explain why it's so beneficial to hide these
>>signatures, from the developers perspective? At least that would provide a
>>solid counter-point.
> 1) I find Stroustrup's argument in the ARM 13.1 (outlined in another
> message) reasonable.
> 2) In my experience with C++, this behavior has not caused an outcry and is
> not listed in any diatribes I've seen as one of the broken features of C++.
> 3) So I am reluctant to break with the C++ rule on this.
> The rule to apply is straightforward - look up the name, *then* apply
> overload resolution.

The rule would still be straightforward if it was:

look up the name, apply overload resolution
if overload resolution fails; repeat above for superclass

Lars Ivar Igesund

July 25, 2004
Walter wrote:
> "Kris" <someidiot@earthlink.dot.dot.dot.net> wrote in message
> news:cdu9ov$162i$1@digitaldaemon.com...
>>Sean; would you mind explaining the benefits of those particular
> resolution
>>rules to me please? While I may be both blind and stupid, I completely
> fail
>>to see where the value lies, and no-one has specified what they are.
> Stroustrup has laid them out in chapter 13.1 of the "The Annotated C++
> Reference Manual." The general rule for overloading is that a name is looked
> up first, and then overload resolution is applied. Stroustrup rejects the
> idea of ignoring scope issues when doing overload resolution. He argues that
> it would be surprising in a deeply nested heirarchy of class derivation,
> that a user of a derived class would have to know too much detail about a
> base class that may be hidden. Also, he shows how surprising errors can
> creep in, such as if a function in base class B copies only the B part of an
> object, but was inadvertantly called with an instance of D that didn't
> override each of those B functions properly.

Sorry, but that example has little to do with overloading, but very much to do with overriding.

The B and D example shows:
A superclass can have a method that cause problems for subclasses if it isn't overridden.

If this problematic situation should be solvable by the language, then a
keyword meaning 'must be overridden' should be included.

mustoverride foo() {}

would mean that subclasses down through the hierarchy *must* override, in some cases doing only super.foo();

Another solution is to have override in the most super class of them all mean that they must be overridden in subclasses, while override in subclasses means what it do today.

What the B and D example don't show:
The public methods of a superclass should be hidden from a subclass' interface, if and only if the subclass have methods with the same name as those in the superclass, regardless of their signature.

Methods are hidden in some cases (those where overloading is involved), even though the normal case is that you don't want to hide. Using alias to unhide is weird. The word alias imply that the real name is hidden, but here it works the other way! The normal case is to want the superclass' methods up there in the subclass, but D has turned this upside down.

Argumentation for why it should work the way it do today is lacking, and the implementation/specification is unintuitive, badly documented and works against most common use.


Lars Ivar Igesund

July 26, 2004
On Sun, 25 Jul 2004 00:06:49 -0700, Walter <newshound@digitalmars.com> wrote:

> "John Reimer" <brk_6502@yahoo.com> wrote in message
> news:pan.2004.
>> > 1) I find Stroustrup's argument in the ARM 13.1 (outlined in another
>> > message) reasonable.
>> As brilliant as he is, could Stroustrup actually be wrong on the matter?
>> Or to put it another way, D is not C++ so why do we have to follow
>> Stroustrup's conventions within a language Stroustrup did not design?
> Heaven knows I disagree with Dr. Stroustrup on many points. However, this is
> a case where I agree with him. I am not simply doing it that way because Dr.
> Stroustrup did it that way.
>> > 2) In my experience with C++, this behavior has not caused an outcry 
>> and
>> > is not listed in any diatribes I've seen as one of the broken features
> of
>> > C++.
>> D is a different language, and this issue is now causing an
>> outcry here that you deny exists elsewhere.  The language seems to be
>> different enough (perhaps because of so many features similar to Java)
>> that this is indeed now an issue. The fact that D has different features
>> from C++ makes a solution to these problems important to the language's
>> future (even if they apparently weren't significant in C++).  Also C++ has
>> it's own community of personalities. The fact that complaints might be
>> nonexistent in that community doesn't imply that the issue isn't important
>> in the D community.
>> What it comes down to is that it seems you have decided to follow C++
>> standards either for convenience or preference.  I guess that's good to
>> know.
> I followed this aspect of C++ because I found the argument in favor of it
> compelling, and since D is a refactoring of C++ and not Java, it gives
> greater weight to C++ behavior over Java behavior.
>> > The rule to apply is straightforward - look up the name, *then* apply
>> > overload resolution.
>> This appears to be a Java verses C++ debate.  Does java define name lookup
>> rules differently (someone indicated so in another message, I believe)?
>> If so, why is the C++ way better then the java way?  The C++
>> model shouldn't always be the right one to imitate, should it?
> Java explicitly differs from C++ in this regard. Kris is arguing for Java
> lookup/overriding rules. I see no reason that Java should be always be the
> right one to imitate, either <g>.

You should choose the one that best suits D. It appears you believe you have done that. It appears Kris disagrees.

So, I am on the fence until I have seen:
 - a good outline of both the C++ and Java name resolution methods.
 - some D code examples where one or the other is better/easier/more intuitive.

I personally find having to use 'alias' counter intuitive. My background is one in C (the last 6 years of my life), not C++ or Java. I have used Java a tiny bit, and C++ perhaps 10x more than that.


Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 26, 2004
"Kris" <someidiot@earthlink.dot.dot.dot.net> wrote in message news:cdvo13$1srb$1@digitaldaemon.com...
> 1)  You'll forgive me Walter, for saying that I think you may just be mistaken in terms of the time period. Recall that you sent me the
> Interface-enabled D compiler (other than COM), and it most certainly did
> have this "Contract Resolution" ability enabled.

At some point it must have worked that way, otherwise Joe wouldn't have sent me that message <g>.

> 2) the example below makes a comment about Interfaces not being inherited. In D they *are* inherited! I've used that time and time again to work
> the ever-persistent "diamond interface" related bugs.
> 3) the example below is built explicitly to circumvent /some/ type system.
> Also, it /could/ be argued that the example below produces a valid and
> predictable result. Regardless, Because D interfaces *are* inherited this
> quite possibly a moot point entirely.

The way interfaces have worked has changed around a bit, some of it was in
response to Joe's emails to me. Interface semantics have several subtleties
that escaped me early on <g>. In any case, what it used to do way back is
not so important, what it does now is, and the type hole would exist if the
inheritance rules would change.
While it certainly would be predictable, so are the other scoping/resolution
rules that you argue are incorrect <g>.

I think this type hole is in the category of ones like:

    class A{} class B:A{}
     B[] b;

which is disallowed. It's better to issue an error when a potential type hole exists, requiring a cast to resolve it, than to silently open such a hole and one's program inexplicably crashes.

> 4) Do you not think this supposed type hole can be worked out in some
> way? The trade-off is, well, I've already documented all the fallout from this decision.

Why is simply omitting the redundant interface name in the inheritance list a problem? I don't get it.

> 5) While not wishing to harp on about Java ~ if this is such a problem,
> does Java avoid it? It manages perfectly well, thank-you-very-much. D is
> supposed to be so much better, right? This "decoupled contract" aspect is
> major player in the Interface arsenel: please do not underestimate it. Here's an extract from my revised document:
> "An Interface is nothing more than a contract. One of the great things
> this notion is there's no implicit binding between the Interface and how
> is actually fulfilled by the implementation. It is perfectly legitimate
> a class to satisfy its contractual obligation in any way it sees fit; including via local methods, via public methods exposed through
> via some base class, via an implemented abstract class, or any combination thereof. That is, the contract can be declared and fulfilled entirely by
> particular class, aggregated piecemeal through inheritance, or be
> itself through some super-class derivation.
> To stipulate otherwise would enforce an implementation restriction that
> no bearing whatsoever upon the contract itself. Under those terms, satisfying the contract would mean ensuring the design of your exposed
> hierarchy matches exactly that of the Interface hierarchy - thus negating the intentionally decoupled nature of the contract."
> Sorry Walter; there's just too many flaws in your statement to be convincing.

July 26, 2004
"Lars Ivar Igesund" <larsivar@igesund.net> wrote in message news:ce1ccn$2ru8$1@digitaldaemon.com...
> Argumentation for why it should work the way it do today is lacking, and the implementation/specification is unintuitive, badly documented and works against most common use.
> All IMHO.

I can concur with "badly documented" <g> but why is the way C++ has worked for 20 years against most common use?

July 26, 2004
"Walter" <newshound@digitalmars.com> wrote in message

> Why is simply omitting the redundant interface name in the inheritance
> a problem? I don't get it.

Ah ... right. There's a total disconnect here, since the original document had an error in it. I guess you didn't get a chance to see the various posts regarding clarification. Please take a look at this revised version, and let's pick up again after that? Thanks, and sorry about the misdirection. The example and grayed-text contained within should hopefully clarify what the issue is ... if not, I'll try to devise an alternate way to state it.


- Kris

July 26, 2004
"Kris" <someidiot@earthlink.dot.dot.dot.net> wrote in message news:cdvrns$1uqn$1@digitaldaemon.com...
> If you can't fix imports to act as though outer-scope methods have somehow been "aliased into scope", then I humbly suggest you make it illegal to allow an import within the class scope.
> I do that all the time for one good reason: all version(linux) and version(Win32) stuff should be isolated together wherever possible. This means I deliberately place imports inside class boundaries, because it is the most maintainable way to set things up (you don't have to go grubbing around trying to find/edit some reference elsewhere). If you make inner imports illegal, then you'll ultimately make the code less maintainable.
> even I would grudgingly admit that's better than the obnoxious behavior
> currently
> exposed.
> Of course, one or the other really has to be remedied: forward references or, uhhhh, smarter name resolution ... current versions of  DMD do not cut it for the former or the latter.

C'mon, Kris! You import the names into a scope, and then want the names to not be found. I don't think that is a resolvable problem. I admit to the documentation being inadequate, but after I explained the 4 simple steps of name lookup rules and when in the process overload resolution applies, the behavior you've seen is straightforward. C++ has loads of magic special rules that apply in arcane situations, and nobody understands them, they just dink around with the source until it appears to work.

I'll be happy to work on any forward referencing issues.

July 26, 2004
"parabolis" <parabolis@softhome.net> wrote in message news:ce12bi$2l2r$1@digitaldaemon.com...
> Walter wrote:
> > You describe it as "The latter is utter nonsense, and smacks of either
> > implementation-specific hack or a half-baked and headless C-style implementation of method hiding." However, consider the following C++ program:
> >
> > --------------------------------------
>    ...
> > -------------------------------------------
> > Now uncomment the 'using' declaration, and the program will compile successfully and produce the 1, 2, 3 output. Therefore, D uses overloading/hiding rules that are completely analogous to C++. I've read
> > lot of critiques of C++, and this has not been mentioned. Or perhaps my
> > compiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.
> >
> I believe this example is misleading. The name resolution is important in C++ only because struct B might inherit from a second struct, say Y, which also implements 'int foo(int i)'. C++ cannot (and would not) be critiqued because it must resolve against multiple super classes. Using C++ rules designed to select from a multiple inheritance hierarchy in D does not make sense.
> I do not believe it is possible to justify hiding anything in a single inheritance language.

C++ had this behavior from the beginning, long before it had multiple inheritance. (Although the 'using' declaration came years after MI was implemented.)

July 26, 2004
>I can concur with "badly documented" <g> but why is the way C++ has worked for 20 years against most common use?

The fact that everyone got used to it doesn't mean it's the best. If people
aren't conscious there are other options, they are not looking for them. Maybe
that's the case going on here.
D is trying to improve on C++, isn't it ?
Ok, just give me a good example that either of the options is right, then make
it work and I'll shut up.

July 26, 2004
"Sha Chancellor" <schancel@pacific.net> wrote in message news:schancel-512344.09114325072004@digitalmars.com...
> If the alias thing is a bug, I disagree on all counts.  I like the option of not including the overloaded members which I didn't overload. There may be cases where a child class does not want those to be inherited.   Which is allowed by the current method. If it becomes the default behavior to inherit them, you'd need to have some kind of convention to get RID of them.

That is another way to look at it. It can be a problem if one has an arbitrarilly deep inheritance heirarchy, and there's an overlooked (!) overload in there. The alias can also be used to 'opt-in' only the functions from a particular subclass in the inheritance heirarchy, not all of them.

The 'alias' idiom for doing an 'opt-in' can be thought of another way - by creating an alias for a symbol in the current scope, doesn't it make sense that it then enables overloading between the scopes on that name? Note that this is the same behavior when one creates an alias for other function names, even names in other imports, etc. It's a powerful thing, but it shouldn't be on by default.

1 2 3 4 5 6 7 8 9 10 11 12 13 14