Discussion:
Inherited explained
(too old to reply)
Anonymous
2008-10-21 15:19:22 UTC
Permalink
I have been unable to understand the inherited clause for many years.
As a result of an explanation given for another problem I was having
recently, I have been able to come up with an understanding of what
this clause means and am going to put out my simplified definition
here. Any correction is welcome.

What inherited infers is basically this: Do what you would have
normally done if I had not taken control of the situation.

An example can be seen below.

------------------------------------------------------------------------
public
{ Public declarations }
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;

procedure TForm1.WMSysCommand;
begin
if (Msg.CmdType = SC_CLOSE) then begin // X button clicked in
upper right hand corner of program interface
...do what needs to be done
end
else
inherited; //inherited means to do what you would have
otherwise done
end;
------------------------------------------------------------------------
--------------------

If the 'else inherited;' had not been placed at the end of the
WMSysCommand procedure, any other sys command messages (example:
SC_MINIMIZE, SC_MAXIMIZE, SC_RESTORE) would have been captured by the
WMSysCommand procedure and would have simply been ignored. As a result
of the presents of the inherited statement, all other sys command
messages are processed as usual as if the WMSysCommand procedure were
not present.
Hans-Peter Diettrich
2008-10-21 15:49:11 UTC
Permalink
Post by Anonymous
else
inherited; //inherited means to do what you would have
otherwise done
end;
This is only one use of inherited, for a default handling of the call.
In other situations you want to do other things, before or after calling
the inherited method to do what is always required.
Post by Anonymous
If the 'else inherited;' had not been placed at the end of the
SC_MINIMIZE, SC_MAXIMIZE, SC_RESTORE) would have been captured by the
WMSysCommand procedure and would have simply been ignored. As a result
of the presents of the inherited statement, all other sys command
messages are processed as usual as if the WMSysCommand procedure were
not present.
Messages should always be handled, somehow. If you handle a message
entirely in your code, it's useless or harmful to pass an already
handled message to another handler.

DoDi
Maarten Wiltink
2008-10-21 17:21:26 UTC
Permalink
Post by Anonymous
I have been unable to understand the inherited clause for many years.
[...]
Post by Anonymous
What inherited infers is basically this: Do what you would have
normally done if I had not taken control of the situation.
That seems a very odd way to describe it.

'Inherited' is a keyword normally applied to a method call - while
it is possible to use it by itself, that is merely a special case,
much like leaving 'Self.' off a method call. Your example with a
message handler is also a further special case because they hide
the appearance of virtual methods overrides.

You can call the inherited version of any other method besides the
current one, or evaluate an inherited property. The usual case,
however, is to call the previous version of the current method.

The modifier becomes useful when applied to a virtual method that
has been overridden in the current class. For such methods, it
specifies to not call the latest override of the method, but to
resolve the name in the immediate parent class instead[0]. (That's
really what it specifies everywhere, of course. And I'm not sure
about the exact implementation of message handlers, but conceptually
and probably practically, they are similar to method overrides.)

This is useful because in class-based object orientation, a class
is expected to inherited and extend the behaviour of its ancestor
classes. Without a way to incur the ancestor class's behaviour,
extension would be impossible. In Object Pascal, 'inherited' is
that way.

So, in a way, what you are saying is not exactly _wrong_. But
it carries a load of assumptions. You seem to be unaware of the
possibility to explicitly mention which method to call. Frankly,
I've never done otherwise, because I don't trust the compiler to
get the parameters right.

But far more worrying is your characterisation of what you are
doing as 'taking control of the situation', where in fact you are
merely building on existing code and behaviour. This suggests to
me that you have a very ad-hoc and antagonistic understanding of
how to build a system of cooperating classes. I think you would
do well to give your base classes more credit. It is normal to
have to override some behaviour here and there, but that is not
indicative of gross errors in existing classes; quite the contrary,
it means that you have recognised that there is much of value in
them that you _can_ re-use.

Or it may merely indicate that you didn't know that 'inherited'
is really about virtual methods and parent classes, and had only
seen it in relation to message handlers. Although in that case,
I would suggest that you have a very fragmented and ad-hoc
understanding of all of Delphi, and would do well to read a book
about it. The OPLG comes to mind; it also explains some more
general programming-related subjects.

You may note that I have inferred (the word being used correctly
this time) quite a lot of your state of mind from one simple turn
of phrase. I may be wrong. Please come back with further questions,
and a tart note of your own when called for.

Groetjes,
Maarten Wiltink

[0] This also means that if a method has not been overridden in the
current class, calling it as 'inherited' makes no difference.
The compiler will _not_ search upwards for the first different previous
version, it will just go up one level before seeing what the method
name means.
Anonymous Remailer
2008-10-21 20:05:14 UTC
Permalink
With all due respect, your knowledge into delphi/pascal has created a
completely incoherent explanation. This is why I have not been able to
completely comprehend the inherited statement before.

I will protest this line, however: 'This suggests to me that you have
a very ad-hoc and antagonistic understanding of how to build a system
of cooperating classes.'

To go into slandering someone's character in your explanation is
patently wrong.
Rudy Velthuis
2008-10-21 21:12:23 UTC
Permalink
Post by Anonymous Remailer
With all due respect, your knowledge into delphi/pascal has created
a completely incoherent explanation.
Then start with a simple tutorial. He used terms one ought to know.
Post by Anonymous Remailer
This is why I have not been
able to completely comprehend the inherited statement before.
I will protest this line, however: 'This suggests to me that you
have a very ad-hoc and antagonistic understanding of how to build a
system of cooperating classes.'
To go into slandering someone's character in your explanation is
patently wrong.
No, it is a realistic assessment. Someone who does not understand what
inherited means can only have such an ad hoc understanding of classes.
So what you should probably do is start from the beginning, with a
simple tutorial about object oriented programming, if possible about
Delphi. It can't hurt, and even seasoned programmers should, IMO,
sometimes do that.

But just in case you come from a different language: In a method,
inherited calls a function in the base class, it is like .NET's
base.somecall(), which also calls the function somecall() in the direct
ancestor of the current class in the inheritance hierarchy.

Inherited without a function name will call the method of the same name
as the current one, with the same parameters, in the direct ancestor
class. The difference with a call to inherited with a function name is
that if there is no method to be called in the direct ancestor, it will
simply be ignored.

Example:

type
Base = class
...
procedure DoSomething(I: Integer); virtual;
...
end;

Derived = class
...
procedure DoSomething(I: Integer); override;
procedure SomethingElse(C: Char);
...
end;

procedure Base.DoSomething(I: Integer);
begin
Writeln('Do something in Base');
end;

procedure Derived.DoSomething(I: Integer);
begin
inherited; // calls Base.DoSomething(I);
Writeln('Do something in Derived');
end;

procedure Derived.SomethingElse(C: Char);
begin
inherited; // does nothing, since there is no Base.SomethingElse
inherited SomethingElse(C);
// error, since there is no Base.SomethingElse
end;
--
Rudy Velthuis http://rvelthuis.de

"I'm not into working out. My philosophy: No pain, no pain."
-- Carol Leifer.
Justus J.
2008-10-21 22:43:42 UTC
Permalink
Post by Rudy Velthuis
...
type
Base = class
...
procedure DoSomething(I: Integer); virtual;
...
end;
Derived = class
...
procedure DoSomething(I: Integer); override;
procedure SomethingElse(C: Char);
...
end;
...
I assume it should read

Derived = class(Base)

or else I'm totally lost here.

Justus
Rudy Velthuis
2008-10-21 22:46:17 UTC
Permalink
Post by Justus J.
Post by Rudy Velthuis
...
type
Base = class
...
procedure DoSomething(I: Integer); virtual;
...
end;
Derived = class
...
procedure DoSomething(I: Integer); override;
procedure SomethingElse(C: Char);
...
end;
...
I assume it should read
Derived = class(Base)
or else I'm totally lost here.
Yes, of course, of course. Stupid error. <g>
--
Rudy Velthuis http://rvelthuis.de

"Our government has kept us in a perpetual state of fear - kept
us in a continuous stampede of patriotic fervor - with the cry
of grave national emergency." -- General Douglas MacArthur
Maarten Wiltink
2008-10-21 21:12:32 UTC
Permalink
Post by Anonymous Remailer
With all due respect, your knowledge into delphi/pascal has created a
completely incoherent explanation. This is why I have not been able to
completely comprehend the inherited statement before.
I'm a lousy teacher. For that exact reason. I thought it was pretty
coherent myself, but then, I already knew all that stuff.
Post by Anonymous Remailer
I will protest this line, however: 'This suggests to me that you have
a very ad-hoc and antagonistic understanding of how to build a system
of cooperating classes.'
So refute it.

The impression you make on me is that of a cargo cult programmer.
My guess is that you've read a lot of example code, have understood
it partly[0], and have not gone so far as to look up the word
inherited in the help file.

I consider that the wrong approach.
Post by Anonymous Remailer
To go into slandering someone's character in your explanation is
patently wrong.
It's only slander if it isn't true.

So when I say that you appear to have taught yourself a programming
style of fighting the system, instead of making the system work for you
(and we've seen a *lot* of people like that here, so I may be biased),
all you have to do is convince me that I'm wrong.

Plus, I haven't said that you were stupid or hopeless, right? You
got two reactions so far, both from people who (if I do say so myself)
are very good at this and considered your article interesting and
worthy of a constructive reply. You'll have to take my word for it
that I _did_ mean it like that.

Groetjes,
Maarten Wiltink

[0] You may consider that faint praise, but it places you ahead of
some people.
Jamie
2008-10-21 22:07:45 UTC
Permalink
Post by Anonymous Remailer
With all due respect, your knowledge into delphi/pascal has created a
completely incoherent explanation. This is why I have not been able to
completely comprehend the inherited statement before.
I will protest this line, however: 'This suggests to me that you have
a very ad-hoc and antagonistic understanding of how to build a system
of cooperating classes.'
To go into slandering someone's character in your explanation is
patently wrong.
If you understand Linked List... Just think of a list of pointers
all pointing to class methods and your newly overridden class procedure
simply added it self to the top of the list.. The "inherited" points to
the procedure just before yours. And that procedure will then have it's
inherited pointer that points to the procedure before that one and so on.
The one on top gets it first as in all cases of nature!//

Maybe that explanation will be clearer to you.

there is a little more processing going on in the background but I
think you get the idea.

http://webpages.charter.net/jamie_5"
Rudy Velthuis
2008-10-21 22:47:09 UTC
Permalink
Post by Anonymous Remailer
With all due respect, your knowledge into delphi/pascal has created
a completely incoherent explanation.
Then start with a simple tutorial. He used terms one ought to know.
Post by Anonymous Remailer
This is why I have not been
able to completely comprehend the inherited statement before.
I will protest this line, however: 'This suggests to me that you
have a very ad-hoc and antagonistic understanding of how to build a
system of cooperating classes.'
To go into slandering someone's character in your explanation is
patently wrong.
No, it is a realistic assessment. Someone who does not understand what
inherited means can only have such an ad hoc understanding of classes.
So what you should probably do is start from the beginning, with a
simple tutorial about object oriented programming, if possible about
Delphi. It can't hurt, and even seasoned programmers should, IMO,
sometimes do that.

But just in case you come from a different language: In a method,
inherited calls a function in the base class, it is like .NET's
base.somecall(), which also calls the function somecall() in the direct
ancestor of the current class in the inheritance hierarchy.

Inherited without a function name will call the method of the same name
as the current one, with the same parameters, in the direct ancestor
class. The difference with a call to inherited with a function name is
that if there is no method to be called in the direct ancestor, it will
simply be ignored.

Example:

type
Base = class
...
procedure DoSomething(I: Integer); virtual;
...
end;

Derived = class(Base)
...
procedure DoSomething(I: Integer); override;
procedure SomethingElse(C: Char);
...
end;

procedure Base.DoSomething(I: Integer);
begin
Writeln('Do something in Base');
end;

procedure Derived.DoSomething(I: Integer);
begin
inherited; // calls Base.DoSomething(I);
Writeln('Do something in Derived');
end;

procedure Derived.SomethingElse(C: Char);
begin
inherited; // does nothing, since there is no Base.SomethingElse
inherited SomethingElse(C);
// error, since there is no Base.SomethingElse
end;
--
Rudy Velthuis http://rvelthuis.de

"After every 'victory' you have more enemies."
-- Jeanette Winterson
Rudy Velthuis
2008-10-21 21:15:34 UTC
Permalink
Post by Anonymous
procedure WMSysCommand(var Msg: TWMSysCommand); message
WM_SYSCOMMAND;
procedure TForm1.WMSysCommand;
begin
if (Msg.CmdType = SC_CLOSE) then begin // X button clicked in
upper right hand corner of program interface
...do what needs to be done
end
else
inherited; //inherited means to do what you would have
otherwise done
end;
"inherited;" on its own means here: call WMSysCommand(Msg) in the
ancestor class, but only if there is such a method in that class.
Otherwise, ignore the call.

Now "inherited WMSysCommand(Msg);" would also have been possible, but
that would cause a compiler error if the ancestor does not have a
WMSysCommand.
--
Rudy Velthuis http://rvelthuis.de

"It is only those who have neither fired a shot nor heard the
shrieks and groans of the wounded who cry aloud for blood...
War is hell." -- General William Tecumseh Sherman
Rob Kennedy
2008-10-22 06:53:50 UTC
Permalink
Post by Rudy Velthuis
Post by Anonymous
procedure WMSysCommand(var Msg: TWMSysCommand); message
WM_SYSCOMMAND;
procedure TForm1.WMSysCommand;
begin
if (Msg.CmdType = SC_CLOSE) then begin // X button clicked in
upper right hand corner of program interface
...do what needs to be done
end
else
inherited; //inherited means to do what you would have
otherwise done
end;
"inherited;" on its own means here: call WMSysCommand(Msg) in the
ancestor class, but only if there is such a method in that class.
Otherwise, ignore the call.
In this case, it doesn't necessarily mean to call WMSysCommand. Rather,
it means to call the next-less-derived method that's also marked with
"message wm_SysCommand." The name of the method doesn't matter. And
furthermore, if the ancestor doesn't have a wm_SysCommand handler, then
it will call the virtual TObject.DefaultHandler method instead.
Post by Rudy Velthuis
Now "inherited WMSysCommand(Msg);" would also have been possible, but
that would cause a compiler error if the ancestor does not have a
WMSysCommand.
And it could also lead to skipping over some method if there were
another handler for the same message but that happened to use a
different name.

Some examples:

type
TOne = class
procedure WMSysCommand(var Msg); message wm_SysCommand;
end;

TTwo = class(TOne)
procedure SysCommandHandler(var Msg: TWMSysCommand); message
wm_SysCommand;
end;

TThree = class(TTwo)
procedure WMSysCommand(var Msg): message wm_SysCommand;
end;

procedure TOne.WMSysCommand;
begin
inherited; // Calls TObject.DefaultHandler(Msg)

inherited WMSysCommand(Msg); // Compiler error
end;

procedure TTwo.SysCommandHandler;
begin
inherited; // Calls TOne.WMSysCommand(Msg)

inherited WMSysCommand(Msg); // Call TOne.WMSysCommand(Msg)

inherited SyCommandHandler(Msg); // Compiler error
end;

procedure TThree.WMSysCommand;
begin
inherited; // Calls TTwo.SysCommandHandler(Msg)

inherited WMSysCommand(Msg); // Calls TOne.WMSysCommand(Msg)
end;
--
Rob
Rudy Velthuis
2008-10-22 11:18:59 UTC
Permalink
Post by Rudy Velthuis
Post by Anonymous
procedure WMSysCommand(var Msg: TWMSysCommand); message
WM_SYSCOMMAND;
procedure TForm1.WMSysCommand;
begin
if (Msg.CmdType = SC_CLOSE) then begin // X button clicked in
upper right hand corner of program interface >> ...do what
needs to be done >> end
Post by Rudy Velthuis
Post by Anonymous
else
inherited; //inherited means to do what you would have
otherwise done
Post by Rudy Velthuis
Post by Anonymous
end;
"inherited;" on its own means here: call WMSysCommand(Msg) in the
ancestor class, but only if there is such a method in that class.
Otherwise, ignore the call.
In this case, it doesn't necessarily mean to call WMSysCommand.
Rather, it means to call the next-less-derived method that's also
marked with "message wm_SysCommand."
That is true for message handlers indeed. Not the name is searched, but
the same slot in the dynamic method table. But we can generally assume
it will also be called WMSysCommand, if people followed the tradition.
<g>
--
Rudy Velthuis http://rvelthuis.de

"RAM /abr./: Rarely Adequate Memory." -- From the Jargon File
Continue reading on narkive:
Loading...