June 09, 2004
Stewart Gordon wrote:

> Arcane Jill wrote:
> 
> <snip>
>> The default implementation in Object returns CompareResult.NOT_COMPARABLE. That would make all objects essentially uncomparable UNLESS you overrode opCmp. As a beneficial side-effect, this would also enable you to REMOVE comparability in a derived class. For example, imagine we had a class Real that was comparable. You might want to derive a class Complex which was incomparable. With this scheme, you could do that.
> 
> A complex number isn't a kind of real number.
> 
> An array of reals is exactly that - an array of reals.  Reals being comparable makes it possible to do such things as sort and binary search.  If there is the odd complex number mixed in, then it isn't an array of reals anymore, even if the declaration confusingly says it is.
> 
> Subclasses are supposed to extend functionality, not remove functionality.

True. Interestingly: subclassing in OO programming is very similar to taking a subset in mathematics. real is a subset of complex. This subset is not closed under operations like sqrt, but as a subset of complex, real numbers offer everything complex number offer, and even more (like comparing).

For class design, this relation is not very practical: It would not make much sense to derive real from a complex class, but from the mathematics point of view, that would be the correct way to do it.

June 09, 2004
Arcane Jill wrote:

> In article <ca3l2n$2rv1$1@digitaldaemon.com>, Jeroen van Bemmel says...
> 
>>perhaps add syntax like:
>>
>>class A {
>>  int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
>>}
> 
> Actually, this is a pretty neat idea. In general, you might want to say that a class B which subclasses class A might want to *remove* features which A offered (as opposed to adding them, which is the normal thing to do). Another example might be: A has a function serialize(), but B (which subclasses A) does not, so you want to somehow forbid b.serialize(). The normal way this is done is to override the disallowed function with a function which throws an exeption or asserts, but it would be nice to have another way.

This goes completely contrary to all concepts of OO: Polymorphism and inheritance say that a subclass has all capabilities of the parent class.

If you want to disallow a feature in a subclass, that is either a sign of lazyness of bad design. Sometimes, throwing an assert(0) may be feasible, but the compiler will never be able to handle that kind of "disallowing" at compile-time.


June 09, 2004
"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message news:ca6l6r$1pkv$1@digitaldaemon.com...
> Ivan Senji wrote:
> <snip>
> >> There are probably plenty of classes of which two instances cannot be equal in any meaningful sense.  For these, it only makes sense to compare the object references.  So it provides this default behaviour.
> >
> > Exactly! But we are obviously thinking from the oposite sides :) If 2 instances of a class cannot be compared i wan't a==b to be illegal! What is === or "is" for? It is there to compare references to instances for identity. I don't believe there can be a default
behaviour
> > for == for classes that can't be compared!
>
> They can be compared.  They just compare unequal if they're not the same object.

And again IMHO that is what === is for.

> This enables them to be used in container templates for such things as keys and searching.  There's no reason I can see for a class designer's wanting to prevent all users of the class from doing this.

Doing what? Comparing for identity? I would prefer that a class that hasn't got these operators defined can't be used in such containers because if the author didn't implement these operators maybe ha was trying to say that it makes no sense.

This causes problems when someone forgets to implement them and
default version is used. This is a good example of what a standard mixin
could be. If you wanted the default strange behavior you just do:
class A
{
    mixnin opEqualsAndCmp();
    //...
}

If nothing comes from these discussion i would like to make a feature request <ironic> to implement opAdd in object, that calculates the sum of adresses of the 2 added objects...</ironic> :)

By the way, noone has answered to me: Does anyones code depend on
this strange feature? Are there any good reasons (not solvable by mixins)
for defending this?

> Stewart.
>
> --
> My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment.  Please keep replies on the 'group where everyone may benefit.


June 09, 2004
Ivan Senji wrote:
<snip>
>> This enables them to be used in container templates for such things as
>> keys and searching.  There's no reason I can see for a class designer's
>> wanting to prevent all users of the class from doing this.
> 
> Doing what? Comparing for identity? I would prefer that a class that
> hasn't got these operators defined can't be used in such containers because
> if the author didn't implement these operators maybe ha was trying to say
> that it makes no sense.
<snip>

No.  Ha was saying that only one instance of the class can conceivably have the same value.

Stewart.

-- 
My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment.  Please keep replies on the 'group where everyone may benefit.
June 09, 2004
On Wed, 09 Jun 2004 12:52:13 +0200, Norbert Nemec wrote:

> Arcane Jill wrote:
> 
>> In article <ca3l2n$2rv1$1@digitaldaemon.com>, Jeroen van Bemmel says...
>> 
>>>perhaps add syntax like:
>>>
>>>class A {
>>>  int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
>>>}
>> 
>> Actually, this is a pretty neat idea. In general, you might want to say that a class B which subclasses class A might want to *remove* features which A offered (as opposed to adding them, which is the normal thing to do). Another example might be: A has a function serialize(), but B (which subclasses A) does not, so you want to somehow forbid b.serialize(). The normal way this is done is to override the disallowed function with a function which throws an exeption or asserts, but it would be nice to have another way.
> 
> This goes completely contrary to all concepts of OO: Polymorphism and inheritance say that a subclass has all capabilities of the parent class.
> 
> If you want to disallow a feature in a subclass, that is either a sign of lazyness of bad design. Sometimes, throwing an assert(0) may be feasible, but the compiler will never be able to handle that kind of "disallowing" at compile-time.

Norbert,
are you saying that its okay for this type of thing to be a run-time error
but not a compile-time error? Isn't that what the request is really about?
That is, let's change this technique from a run-time test to one that is
detected at compile-time instead.

Let's say that somebody has written a Real Neat Class (RNC) that has a sorting method in it. Now I wish to create a new class based on this but sorting is not really sensible for it, so I wish to prevent the sort method from *ever* being used. Yes, I could write a sort method that caused a run-time effect (eg. throw an exception), or if we had a disable facility, to tell the compiler that I'm explictly disallowing any code to call the parent's sort method.

I think that in principle, compile-time error detection is better than run-time detection.

-- 
Derek
Melbourne, Australia
June 09, 2004
Derek wrote:

> Norbert,
> are you saying that its okay for this type of thing to be a run-time error
> but not a compile-time error? Isn't that what the request is really about?
> That is, let's change this technique from a run-time test to one that is
> detected at compile-time instead.
> 
> Let's say that somebody has written a Real Neat Class (RNC) that has a sorting method in it. Now I wish to create a new class based on this but sorting is not really sensible for it, so I wish to prevent the sort method from *ever* being used. Yes, I could write a sort method that caused a run-time effect (eg. throw an exception), or if we had a disable facility, to tell the compiler that I'm explictly disallowing any code to call the parent's sort method.
> 
> I think that in principle, compile-time error detection is better than run-time detection.

The last statement is true, but it this case cannot, in general, be detected at compile-time:

--------
class A {
        void something() {
                do_something();
        }
}

class B: A {
        void something() {
                assert(0);
        }
}

A a = new B();
a.something();
--------

Polymorphism means that an object of type B can be used via a type A reference. The compiler does not know what the reference points to. If you want to disable the function in the inheriting class, you are obviously working against polymorphism, i.e. you are abusing object-oriented tools (like inheritance) in some way, which I would call "faulty design".

June 09, 2004
Norbert Nemec wrote:
<snip>
> class A {
>         void something() {
>                 do_something();
>         }
> }
> 
> class B: A {
>         void something() {
>                 assert(0);
>         }
> }
> 
> A a = new B();
> a.something();
> --------
> 
> Polymorphism means that an object of type B can be used via a type A
> reference. The compiler does not know what the reference points to. If you
> want to disable the function in the inheriting class, you are obviously
> working against polymorphism, i.e. you are abusing object-oriented tools
> (like inheritance) in some way, which I would call "faulty design".

Not to mention using it to indicate 'not yet implemented'....

Stewart.

-- 
My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment.  Please keep replies on the 'group where everyone may benefit.
June 09, 2004
Derek wrote:

> are you saying that its okay for this type of thing to be a run-time error
> but not a compile-time error? Isn't that what the request is really about?
> That is, let's change this technique from a run-time test to one that is
> detected at compile-time instead.
> 
> Let's say that somebody has written a Real Neat Class (RNC) that has a
> sorting method in it. Now I wish to create a new class based on this but
> sorting is not really sensible for it, so I wish to prevent the sort method
> from *ever* being used. Yes, I could write a sort method that caused a
> run-time effect (eg. throw an exception), or if we had a disable facility,
> to tell the compiler that I'm explictly disallowing any code to call the
> parent's sort method.

Since your RealNeatSubclass is-a RealNeatClass, there's a problem if it be used any place a RNC is needed.  Further, compile-time checking for this sort of thing will be incomplete at best.

RNC rnc = new RealNeatSubclass();
if (rnc < otherRnc) // the compiler can't help you here

Polymorphism can't be used to subtract behaviours from a class.

(this is why Object mustn't define opCmp or opEquals, incidently)

 -- andy
June 09, 2004
"Andy Friesen" <andy@ikagames.com> wrote in message news:ca7gof$22p$1@digitaldaemon.com...
> Derek wrote:
>
> > are you saying that its okay for this type of thing to be a run-time
error
> > but not a compile-time error? Isn't that what the request is really
about?
> > That is, let's change this technique from a run-time test to one that is detected at compile-time instead.
> >
> > Let's say that somebody has written a Real Neat Class (RNC) that has a sorting method in it. Now I wish to create a new class based on this but sorting is not really sensible for it, so I wish to prevent the sort
method
> > from *ever* being used. Yes, I could write a sort method that caused a run-time effect (eg. throw an exception), or if we had a disable
facility,
> > to tell the compiler that I'm explictly disallowing any code to call the parent's sort method.
>
> Since your RealNeatSubclass is-a RealNeatClass, there's a problem if it be used any place a RNC is needed.  Further, compile-time checking for this sort of thing will be incomplete at best.
>
> RNC rnc = new RealNeatSubclass();
> if (rnc < otherRnc) // the compiler can't help you here
>
> Polymorphism can't be used to subtract behaviours from a class.
>
> (this is why Object mustn't define opCmp or opEquals, incidently)

Why? You dodn't give any explanation why they must be defined!! You just said it. Please explain it to me, what does polymorphism have to do with opCmp and opEquals having to be in a class object.

Why not opAdd and opShl_r?


>   -- andy


June 09, 2004
"Andy Friesen" <andy@ikagames.com> wrote in message news:ca7gof$22p$1@digitaldaemon.com...
> Derek wrote:
>
> > are you saying that its okay for this type of thing to be a run-time
error
> > but not a compile-time error? Isn't that what the request is really
about?
> > That is, let's change this technique from a run-time test to one that is detected at compile-time instead.
> >
> > Let's say that somebody has written a Real Neat Class (RNC) that has a sorting method in it. Now I wish to create a new class based on this but sorting is not really sensible for it, so I wish to prevent the sort
method
> > from *ever* being used. Yes, I could write a sort method that caused a run-time effect (eg. throw an exception), or if we had a disable
facility,
> > to tell the compiler that I'm explictly disallowing any code to call the parent's sort method.
>
> Since your RealNeatSubclass is-a RealNeatClass, there's a problem if it be used any place a RNC is needed.  Further, compile-time checking for this sort of thing will be incomplete at best.
>
> RNC rnc = new RealNeatSubclass();
> if (rnc < otherRnc) // the compiler can't help you here
>
> Polymorphism can't be used to subtract behaviours from a class.
>
> (this is why Object mustn't define opCmp or opEquals, incidently)

SORRY! SORRY! SORRY! I read must :)
I'am glad that there is atleast one person to agree with me on this.
Great!

>   -- andy