Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #26939 > unrolled thread

Inheritance

Started byDoug Hoffman <glidedog@gmail.com>
First post2013-11-25 06:59 -0500
Last post2013-11-27 11:58 -0600
Articles 15 — 5 participants

Back to article view | Back to comp.lang.forth


Contents

  Inheritance Doug Hoffman <glidedog@gmail.com> - 2013-11-25 06:59 -0500
    Re: Inheritance Bernd Paysan <bernd.paysan@gmx.de> - 2013-11-25 20:01 +0100
      Re: Inheritance Doug Hoffman <glidedog@gmail.com> - 2013-11-26 05:11 -0500
        Re: Inheritance Bernd Paysan <bernd.paysan@gmx.de> - 2013-11-26 22:09 +0100
      Re: Inheritance the_gavino_himself <visphatesjava@gmail.com> - 2013-11-27 15:25 -0800
        Re: Inheritance Bernd Paysan <bernd.paysan@gmx.de> - 2013-11-28 01:39 +0100
          Re: Inheritance Mark Wills <markrobertwills@yahoo.co.uk> - 2013-11-28 01:53 -0800
    Re: Inheritance Andrew Haley <andrew29@littlepinkcloud.invalid> - 2013-11-25 15:28 -0600
      Re: Inheritance Doug Hoffman <glidedog@gmail.com> - 2013-11-26 05:11 -0500
        Re: Inheritance Bernd Paysan <bernd.paysan@gmx.de> - 2013-11-26 22:28 +0100
          Re: Inheritance Doug Hoffman <glidedog@gmail.com> - 2013-11-26 17:12 -0500
            Re: Inheritance Bernd Paysan <bernd.paysan@gmx.de> - 2013-11-27 23:07 +0100
        Re: Inheritance Andrew Haley <andrew29@littlepinkcloud.invalid> - 2013-11-26 17:11 -0600
          Re: Inheritance Doug Hoffman <glidedog@gmail.com> - 2013-11-27 06:25 -0500
            Re: Inheritance Andrew Haley <andrew29@littlepinkcloud.invalid> - 2013-11-27 11:58 -0600

#26939 — Inheritance

FromDoug Hoffman <glidedog@gmail.com>
Date2013-11-25 06:59 -0500
SubjectInheritance
Message-ID<52933ba3$0$294$14726298@news.sunsite.dk>
I have been reading that inheritance is falling from favor when using 
OOP.  I agree that inheritance overuse can lead to harder to 
read/understand/debug code.  Of course the use of inheritance is 
completely controlled by the programmer.  Seems to me that using 
inheritance more sparingly should lead to the following:

1) One should embed objects as instance variables (the "has a" paradigm) 
instead of inheriting (the "is a" paradigm).  At least do so more often 
when needing to add behavior to an object and that behavior already 
exists in another class.  Sometimes, though, using shallow inheritance 
is the best way to go because more "pass-through" methods need not then 
be defined.

2) Late binding to self (aka open recursion) is only used with 
inheritance.  So if we are not using inheritance as much then the 
default for messages to self should be an early bind for speed.  Late 
binding can still be used when wanted (use a syntax such as [self]).

3) Early binding to self should make using inheritance easier and less 
prone to bugs.  Not to say that late binding to self(inheritance) should 
never be used.  Sometimes it is perfect and greatly enhances code reuse, 
but again only with inheritance.

4) Messages sent to objects-as-instance-variables should always be early 
bound, again for speed.  The class compiler can do this transparently 
because the class of the object is known at compile time and the class 
of the embedded object will not change.  Of course objects in a 
*container* instance variable could be of any class and so late binding 
is then required (also done transparently).  No extra effort needed from 
the programmer either way.

The above techniques will result in object-oriented code that is 
noticeably faster and easier to write and maintain.

-Doug

[toc] | [next] | [standalone]


#26949

FromBernd Paysan <bernd.paysan@gmx.de>
Date2013-11-25 20:01 +0100
Message-ID<l706q6$c5o$1@online.de>
In reply to#26939
Doug Hoffman wrote:

> I have been reading that inheritance is falling from favor when using
> OOP.  I agree that inheritance overuse can lead to harder to
> read/understand/debug code.  Of course the use of inheritance is
> completely controlled by the programmer.  Seems to me that using
> inheritance more sparingly should lead to the following:
> 
> 1) One should embed objects as instance variables (the "has a" paradigm)
> instead of inheriting (the "is a" paradigm).  At least do so more often
> when needing to add behavior to an object and that behavior already
> exists in another class.  Sometimes, though, using shallow inheritance
> is the best way to go because more "pass-through" methods need not then
> be defined.
> 
> 2) Late binding to self (aka open recursion) is only used with
> inheritance.  So if we are not using inheritance as much then the
> default for messages to self should be an early bind for speed.  Late
> binding can still be used when wanted (use a syntax such as [self]).
> 
> 3) Early binding to self should make using inheritance easier and less
> prone to bugs.  Not to say that late binding to self(inheritance) should
> never be used.  Sometimes it is perfect and greatly enhances code reuse,
> but again only with inheritance.
> 
> 4) Messages sent to objects-as-instance-variables should always be early
> bound, again for speed.  The class compiler can do this transparently
> because the class of the object is known at compile time and the class
> of the embedded object will not change.  Of course objects in a
> *container* instance variable could be of any class and so late binding
> is then required (also done transparently).  No extra effort needed from
> the programmer either way.
> 
> The above techniques will result in object-oriented code that is
> noticeably faster and easier to write and maintain.

You forgot one important thing, that is the "combination" stuff.  You might 
not have deep inheritance trees, but combine different objects into one.

E.g.: In MINOS, every widget has an actor.  An actor is a class that gets 
called for actions, like clicks or keystrokes.  There are not too many actor 
classes with the same interface; usually they don't inherit from each other 
(so the hierarchy is flat).

Those actors are not instance variables, but instance pointers.  Calling 
them absolutely requires polymorphism.

The typical case I found for calling with self are "template methods", i.e. 
methods that do something that is filled further down in the inheritance 
tree.  That also absolutely requires late binding.

I don't understand why you are so obsessed with early binding, and argue 
with speed.  Contemporary CPUs do quite well on vtable dispatches with their 
branch target buffers.  They don't do well with a central dispatcher that is 
more complicated than a simple vtable call, so if you want speed, just make 
sure that you can implement your system using a vtable.  The case where you 
actually don't have polymorphism (same method called each time) is as fast 
as the direct call on a Core i7, so this particular case of optimization has 
aleady been done by the CPU manufacturer.

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

[toc] | [prev] | [next] | [standalone]


#26963

FromDoug Hoffman <glidedog@gmail.com>
Date2013-11-26 05:11 -0500
Message-ID<529473d1$0$297$14726298@news.sunsite.dk>
In reply to#26949
On 11/25/13 2:01 PM, Bernd Paysan wrote:

> You forgot one important thing, that is the "combination" stuff.  You might
> not have deep inheritance trees, but combine different objects into one.

> Those actors are not instance variables, but instance pointers.

Are you talking about "instance variables" that are actually embedded 
objects?  If not what are they?  In FMS these are first-class-objects, 
not pointers to objects.  Yes, the instance variables of an object are 
first class objects themselves.


> The typical case I found for calling with self are "template methods", i.e.
> methods that do something that is filled further down in the inheritance
> tree.  That also absolutely requires late binding.

"further down in the inheritance tree".  I was talking about no 
inheritance or shallow inheritance.


> I don't understand why you are so obsessed with early binding, and argue
> with speed.

Because speed is important.  So is code size.

> Contemporary CPUs do quite well on vtable dispatches with their
> branch target buffers.  They don't do well with a central dispatcher that is
> more complicated than a simple vtable call, so if you want speed, just make
> sure that you can implement your system using a vtable.

If *all* method calls are through vtables then table sizes can get 
large.  This can be a problem.  If large table sizes aren't a concern 
then I agree with your conclusion.

-Doug

[toc] | [prev] | [next] | [standalone]


#26982

FromBernd Paysan <bernd.paysan@gmx.de>
Date2013-11-26 22:09 +0100
Message-ID<l732ms$h9k$1@online.de>
In reply to#26963
Doug Hoffman wrote:

> On 11/25/13 2:01 PM, Bernd Paysan wrote:
> 
>> You forgot one important thing, that is the "combination" stuff.  You
>> might not have deep inheritance trees, but combine different objects into
>> one.
> 
>> Those actors are not instance variables, but instance pointers.
> 
> Are you talking about "instance variables" that are actually embedded
> objects?  If not what are they?  In FMS these are first-class-objects,
> not pointers to objects.  Yes, the instance variables of an object are
> first class objects themselves.

No, I'm very deliberate and did say they are pointed to, and not direct 
instances.  The reason for that is that they can be different classes, and 
different classes have different sizes.  All they have in common is the same 
interface.  They are first-class, too.

You really have to try this, sticking objects together like this to obtain 
various different behavior.  It's a very common design pattern.

>> The typical case I found for calling with self are "template methods",
>> i.e. methods that do something that is filled further down in the
>> inheritance
>> tree.  That also absolutely requires late binding.
> 
> "further down in the inheritance tree".  I was talking about no
> inheritance or shallow inheritance.

Shallow inheritance usually has one level further down.  That's completely 
enough to justify such template methods.

>> I don't understand why you are so obsessed with early binding, and argue
>> with speed.
> 
> Because speed is important.  So is code size.

You missed the point: Speed is not an issue with vtable based late binding, 
nor is code size.  The late binding call is as big as the early binding call 
on x86 (native code assumed, of course).  2 bytes for the fetch the vtable, 
3 bytes for jump short offset+reg, 5 bytes for a call.  Identical code size, 
and in the case of always using the same class identical speed.  The other 
case (real polymorphism) is slower, but then, it does have a functionality 
which early binding simply doesn't have.

>> Contemporary CPUs do quite well on vtable dispatches with their
>> branch target buffers.  They don't do well with a central dispatcher that
>> is more complicated than a simple vtable call, so if you want speed, just
>> make sure that you can implement your system using a vtable.
> 
> If *all* method calls are through vtables then table sizes can get
> large.  This can be a problem.  If large table sizes aren't a concern
> then I agree with your conclusion.

Agreed, you shouldn't have too many methods in a class.

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

[toc] | [prev] | [next] | [standalone]


#27014

Fromthe_gavino_himself <visphatesjava@gmail.com>
Date2013-11-27 15:25 -0800
Message-ID<cb852263-3b7b-412a-86ad-1502280820fb@googlegroups.com>
In reply to#26949
bernd:

I noticed you added an oo package to gforth.

Why not more functional stuff a la haskell or lisp?

rob pike said oo programming is the roman numerals of computing:

http://harmful.cat-v.org/software/OO_programming/

[toc] | [prev] | [next] | [standalone]


#27018

FromBernd Paysan <bernd.paysan@gmx.de>
Date2013-11-28 01:39 +0100
Message-ID<l763bt$tb8$1@online.de>
In reply to#27014
the_gavino_himself wrote:

> bernd:
> 
> I noticed you added an oo package to gforth.

A variant of Mini-OOF with current object; this is really small stuff.  
Unlike the previous Mini-OOF, it feels complete enough so that I can do 
actual work with it.

> Why not more functional stuff a la haskell or lisp?

Because that would be considerably more complex, and for the things I want 
to do less useful.

> rob pike said oo programming is the roman numerals of computing:
> 
> http://harmful.cat-v.org/software/OO_programming/

I'm totally with them: The way most people use OOP is to add layers and 
layers of abstraction just to delegate work to somebody else.  That's not 
what I want to do.  OOP has some specific places where it is useful, it is 
no silver bullet and not the be all and end all.

For GUIs however, it has been shown its usefulness.  And that's where I'm 
using it.

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

[toc] | [prev] | [next] | [standalone]


#27027

FromMark Wills <markrobertwills@yahoo.co.uk>
Date2013-11-28 01:53 -0800
Message-ID<4083b20a-bcf0-4e97-acdb-3ce812b59381@googlegroups.com>
In reply to#27018
On Thursday, November 28, 2013 12:39:25 AM UTC, Bernd Paysan wrote:
> I'm totally with them: The way most people use OOP is to add layers and 
> layers of abstraction just to delegate work to somebody else.  That's not 
> what I want to do.  OOP has some specific places where it is useful, it is 
> no silver bullet and not the be all and end all.
> 
> For GUIs however, it has been shown its usefulness.  And that's where I'm 
> using it.

Totally agree (FWIW). I'm finding it (OOP) great for SCADA too, where you have literally thousands of objects of the same type. It's perfect. The 'art' is, like you say, not to get too carried away with it. Some OOP (Java is a particular offender I think) just goes way way too far. It's like the programmers are showing off or something!

[toc] | [prev] | [next] | [standalone]


#26951

FromAndrew Haley <andrew29@littlepinkcloud.invalid>
Date2013-11-25 15:28 -0600
Message-ID<96ednQd94ZBxXQ7PnZ2dnUVZ_h-dnZ2d@supernews.com>
In reply to#26939
Doug Hoffman <glidedog@gmail.com> wrote:
> I have been reading that inheritance is falling from favor when using 
> OOP. 

Well, maybe.  I suspect that inheritance has been rather overused in
some areas, and this is a much needed correction.  "is-a" really only
makes sense if the object really is an X.

> 2) Late binding to self (aka open recursion) is only used with 
> inheritance.  So if we are not using inheritance as much then the 
> default for messages to self should be an early bind for speed.  Late 
> binding can still be used when wanted (use a syntax such as [self]).
> 
> 3) Early binding to self should make using inheritance easier and less 
> prone to bugs.

What's the point?  Late binding costs little in practice, so there's
no reason not to use it everywhere.  If a system can optimize it into
early binding, fine.  But it's a waste of the programmer's time to
worry about where things should be early-bound and where not.

> 4) Messages sent to objects-as-instance-variables should always be
> early bound, again for speed.  The class compiler can do this
> transparently because the class of the object is known at compile
> time

In general, no.  Even if you know that your instance variable is an X,
you don't know that it isn't a subclass of X.  Early binding serves
only to restrict the way code can be resued.

> and the class of the embedded object will not change.  Of course
> objects in a *container* instance variable could be of any class and
> so late binding is then required (also done transparently).  No
> extra effort needed from the programmer either way.

> The above techniques will result in object-oriented code that is 
> noticeably faster and easier to write and maintain.

Andrew.

[toc] | [prev] | [next] | [standalone]


#26964

FromDoug Hoffman <glidedog@gmail.com>
Date2013-11-26 05:11 -0500
Message-ID<529473e2$0$292$14726298@news.sunsite.dk>
In reply to#26951
On 11/25/13 4:28 PM, Andrew Haley wrote:
> Doug Hoffman <glidedog@gmail.com> wrote:
>> I have been reading that inheritance is falling from favor when using
>> OOP.
>
> Well, maybe.  I suspect that inheritance has been rather overused in
> some areas, and this is a much needed correction.  "is-a" really only
> makes sense if the object really is an X.
>
>> 2) Late binding to self (aka open recursion) is only used with
>> inheritance.  So if we are not using inheritance as much then the
>> default for messages to self should be an early bind for speed.  Late
>> binding can still be used when wanted (use a syntax such as [self]).
>>
>> 3) Early binding to self should make using inheritance easier and less
>> prone to bugs.
>
> What's the point?  Late binding costs little in practice, so there's
> no reason not to use it everywhere.

"Costs little" is a subjective term.  This is true only for speed and 
only if all vtable calls are used.  See my response to Bernd.  If speed 
*and* code size are important then that changes things.

> If a system can optimize it into
> early binding, fine.  But it's a waste of the programmer's time to
> worry about where things should be early-bound and where not.

With no inheritance or shallow inheritance late binding to self isn't 
done or is done infrequently.


>> 4) Messages sent to objects-as-instance-variables should always be
>> early bound, again for speed.  The class compiler can do this
>> transparently because the class of the object is known at compile
>> time
>
> In general, no.  Even if you know that your instance variable is an X,
> you don't know that it isn't a subclass of X.  Early binding serves
> only to restrict the way code can be resued.

In general *always* with FMS.  The class of the embedded-object-as 
-instance-variable is not going to change.  It doesn't matter if it is a 
subclassed object.  In FMS it is impossible for the class of the 
embedded object to change.  If it is then you are talking about a very 
different object model.  Of course we can store the object *in* an 
instance variable and then yes, late binding *must* be used.  FMS 
supports this as well.  This binding to the embedded object is 
transparent to the programmer.  No restrictions on code reuse.

-Doug

[toc] | [prev] | [next] | [standalone]


#26983

FromBernd Paysan <bernd.paysan@gmx.de>
Date2013-11-26 22:28 +0100
Message-ID<l733q4$in6$1@online.de>
In reply to#26964
Doug Hoffman wrote:
> "Costs little" is a subjective term.  This is true only for speed and
> only if all vtable calls are used.  See my response to Bernd.  If speed
> *and* code size are important then that changes things.

See my response, a vtable call is 2+3 bytes on x86, a direct call is 5 
bytes.  Same number of bytes, same number of cycles (in the branch target 
hit case) on x86.

>> In general, no.  Even if you know that your instance variable is an X,
>> you don't know that it isn't a subclass of X.  Early binding serves
>> only to restrict the way code can be resued.
> 
> In general *always* with FMS.  The class of the embedded-object-as
> -instance-variable is not going to change.

That is a severe limitation.  I've both in BerndOOF, embedded-objects that 
can have only one class, and embedded-by-pointer objects that have the 
identical syntax for use, but can have different classes.  Guess what: I 
never use the fixed, inflexible embedded objects.

And yes, I think when I and you talk, we always talk about completely 
different object models.  That's why I mostly gave up on standardization (of 
the model; maybe some meta stuff can still be standardized): Different 
people have so vastly different understandings of what OOP is, and it's 
always like talking to the blind men with the elephant.  Accept it: OOP is 
bigger than you can comprehend.  I know I'm only using a certain part.  My 
OOP is flexible and strong, but I know it is just next to something rigid 
and inflexible.  I've also seen OOP that is thin and not strong, but makes a 
lot of wind when moved, and OOP which is just a massive body (the "bloat").

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

[toc] | [prev] | [next] | [standalone]


#26986

FromDoug Hoffman <glidedog@gmail.com>
Date2013-11-26 17:12 -0500
Message-ID<52951cdb$0$304$14726298@news.sunsite.dk>
In reply to#26983
On 11/26/13 4:28 PM, Bernd Paysan wrote:
> Doug Hoffman wrote:

>> In general *always* with FMS.  The class of the embedded-object-as
>> -instance-variable is not going to change.
>
> That is a severe limitation.

Sorry if I wasn't clear.  In FMS one can do it either way:

1) Declare the embedded object class.  The class can never change.
2) Store the embedded object in a container instance variable.  The 
object (and class) can change a million+ times during program execution.

No limitations.

> I've both in BerndOOF, embedded-objects that
> can have only one class, and embedded-by-pointer objects that have the
> identical syntax for use, but can have different classes.

You and I are providing the same functionality.

-Doug

[toc] | [prev] | [next] | [standalone]


#27013

FromBernd Paysan <bernd.paysan@gmx.de>
Date2013-11-27 23:07 +0100
Message-ID<l75qfd$g1n$1@online.de>
In reply to#26986
Doug Hoffman wrote:

> On 11/26/13 4:28 PM, Bernd Paysan wrote:
> Sorry if I wasn't clear.  In FMS one can do it either way:
> 
> 1) Declare the embedded object class.  The class can never change.
> 2) Store the embedded object in a container instance variable.  The
> object (and class) can change a million+ times during program execution.
> 
> No limitations.

Great.

>> I've both in BerndOOF, embedded-objects that
>> can have only one class, and embedded-by-pointer objects that have the
>> identical syntax for use, but can have different classes.
> 
> You and I are providing the same functionality.

Then it's fine.  I just so far didn't find a good use for embedded objects 
that have a fixed, unchangeable class.  The unchangeable types usually are 
pretty primitive types like integers, floats, or strings, and as such don't 
need OOP.

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

[toc] | [prev] | [next] | [standalone]


#26988

FromAndrew Haley <andrew29@littlepinkcloud.invalid>
Date2013-11-26 17:11 -0600
Message-ID<vfKdnV3OO8IKtwjPnZ2dnUVZ_jednZ2d@supernews.com>
In reply to#26964
Doug Hoffman <glidedog@gmail.com> wrote:
> On 11/25/13 4:28 PM, Andrew Haley wrote:
>> Doug Hoffman <glidedog@gmail.com> wrote:
>>> I have been reading that inheritance is falling from favor when using
>>> OOP.
>>
>> Well, maybe.  I suspect that inheritance has been rather overused in
>> some areas, and this is a much needed correction.  "is-a" really only
>> makes sense if the object really is an X.
>>
>>> 2) Late binding to self (aka open recursion) is only used with
>>> inheritance.  So if we are not using inheritance as much then the
>>> default for messages to self should be an early bind for speed.  Late
>>> binding can still be used when wanted (use a syntax such as [self]).
>>>
>>> 3) Early binding to self should make using inheritance easier and less
>>> prone to bugs.
>>
>> What's the point?  Late binding costs little in practice, so there's
>> no reason not to use it everywhere.
> 
> "Costs little" is a subjective term.  This is true only for speed and 
> only if all vtable calls are used.  See my response to Bernd.  If speed 
> *and* code size are important then that changes things.

Sure, but the extra flexibility you get means that you can, as a
programmer, get more done in less time because you have more
reusability due to more polymorphism: you can do more with less coding.
In some extreme cases yes, if you really are sunning out of cycles,
you must restrict the design.  But that's a special case.

>> If a system can optimize it into early binding, fine.  But it's a
>> waste of the programmer's time to worry about where things should
>> be early-bound and where not.
> 
> With no inheritance or shallow inheritance late binding to self isn't 
> done or is done infrequently.
>
>>> 4) Messages sent to objects-as-instance-variables should always be
>>> early bound, again for speed.  The class compiler can do this
>>> transparently because the class of the object is known at compile
>>> time
>>
>> In general, no.  Even if you know that your instance variable is an X,
>> you don't know that it isn't a subclass of X.  Early binding serves
>> only to restrict the way code can be resued.
> 
> In general *always* with FMS.  The class of the embedded-object-as 
> -instance-variable is not going to change.  It doesn't matter if it is a 
> subclassed object.  In FMS it is impossible for the class of the 
> embedded object to change.

So, it's an inflexible system that limits reuse.  It means that a setX
method can't be passed an instance of a subclass.  Why do that?  Why
not allow subclassing?

> If it is then you are talking about a very different object model.
> Of course we can store the object *in* an instance variable and then
> yes, late binding *must* be used.

Sorry, you've lost me.  First you say that an instance variable can't
be a subclass, then that it can.

> FMS supports this as well.  This binding to the embedded object is
> transparent to the programmer.  No restrictions on code reuse.

OK, let me try to be clear what I mean about reuse.

The subclass relationship is that wherever an instance of Class X
appears in a program, a subclass Y of Class X may be substituted
without alteration to that program.  All methods of Class X that are
overridden by Class Y will be called as appropriate.  The programmer
does not have to modify any program that uses Class X in order to use
Class Y.  The programmer does not have to modify Class X when writing
Class Y.

This means, in general, that early binding to an object's methods is
impossible because a caller cannot know the true class of an object,
and therefore cannot know which method to call.

Andrew.

[toc] | [prev] | [next] | [standalone]


#26998

FromDoug Hoffman <glidedog@gmail.com>
Date2013-11-27 06:25 -0500
Message-ID<5295d6c1$0$305$14726298@news.sunsite.dk>
In reply to#26988
On 11/26/13 6:11 PM, Andrew Haley wrote:

> Sorry, you've lost me.  First you say that an instance variable can't
> be a subclass

Where did I say that?

> , then that it can.

If the instance variable is a *container*, then that container can hold 
an object of *any* class, subclass or not.  Re-read my original post for 
this thread.  Item 4), 2nd to last sentence.

> OK, let me try to be clear what I mean about reuse.
>
> The subclass relationship is that wherever an instance of Class X
> appears in a program, a subclass Y of Class X may be substituted
> without alteration to that program.  All methods of Class X that are
> overridden by Class Y will be called as appropriate.  The programmer
> does not have to modify any program that uses Class X in order to use
> Class Y.

Except using Class Y will break the program that was designed to use 
Class X if any methods are changed(over ridden) which is usually the case.


> This means, in general, that early binding to an object's methods is
> impossible because a caller cannot know the true class of an object,
> and therefore cannot know which method to call.

In practical terms early binding is often quite possible and useful, and 
can be done transparently (no extra effort by the programmer).  This is 
because the compiler, if written properly, can often know the class of a 
given object.  Sometimes it cannot, sometimes it can.  I say why not use 
this information to advantage?

-Doug

[toc] | [prev] | [next] | [standalone]


#27007

FromAndrew Haley <andrew29@littlepinkcloud.invalid>
Date2013-11-27 11:58 -0600
Message-ID<iqudnZGSPslGrwvPnZ2dnUVZ_gydnZ2d@supernews.com>
In reply to#26998
Doug Hoffman <glidedog@gmail.com> wrote:
> On 11/26/13 6:11 PM, Andrew Haley wrote:
> 
>> Sorry, you've lost me.  First you say that an instance variable can't
>> be a subclass
> 
> Where did I say that?
> 
>> , then that it can.
> 
> If the instance variable is a *container*, then that container can hold 
> an object of *any* class, subclass or not.  Re-read my original post for 
> this thread.  Item 4), 2nd to last sentence.

Hmm, I see.  So, a container can contain anything, but an instance
variable can't contain any instance other than whatever it was
declared to contain.  But this still seems to me to be a pain: one of
the basic simplifying assumptions of OO is that wherever you see an X,
you can also use a subclass of X.  i.e. if Class Y is a subclass of
Class X, then a Y is an X in every way that a caller cares about.  Its
internal implementation may be different,and it may have extra
functionality, but it's still an X.

>> OK, let me try to be clear what I mean about reuse.
>>
>> The subclass relationship is that wherever an instance of Class X
>> appears in a program, a subclass Y of Class X may be substituted
>> without alteration to that program.  All methods of Class X that are
>> overridden by Class Y will be called as appropriate.  The programmer
>> does not have to modify any program that uses Class X in order to use
>> Class Y.
> 
> Except using Class Y will break the program that was designed to use
> Class X if any methods are changed(over ridden) which is usually the
> case.

It shouldn't do, as long as the contract of Class X isn't broken.
That's a matter of good object-oriented design.  If Class Y is a
subclass of X, then it honours the contract of X.  No program that is
designed to use an X will break.  If a class Y doesn't honour the
contract of X, then it should not be a subclass of X.

>> This means, in general, that early binding to an object's methods is
>> impossible because a caller cannot know the true class of an object,
>> and therefore cannot know which method to call.
> 
> In practical terms early binding is often quite possible and useful,
> and can be done transparently (no extra effort by the programmer).
> This is because the compiler, if written properly, can often know
> the class of a given object.  Sometimes it cannot, sometimes it can.
> I say why not use this information to advantage?

That's the good kind of early binding.  That's the kind everyone
likes.  The bad kind of early binding is the kind that restricts
reuse.  The problem here in c.l.f is usuelly that people don't clarify
which kind they mean when they say "early binding".

Good early binding is just an optimization that the system performs,
transparently to the programmer.  Bad early binding is what I've seen
in some OO Forths where a method is early bound explicitly by the
programmer at a call site in the knowledge that this will "always be
an instance of Class X".  It's just an accident waiting to happen.

Andrew.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.forth


csiph-web