Solved

Chained Inheritance -- overriding and inherited

Posted on 1997-04-11
17
293 Views
Last Modified: 2010-07-27
This should be simple question...am in the middle of redesigning some classes using a newly designed base class.

My question:

My base class is derived from TGraphicControl (I'm designing a component base class for designing components of similar, yet extended, functionality).  My actual components are derived from CSimBaseDevice.  Here is some code.

CSimBaseDevice = class(TGraphicControl)
    ....
end;

CSimGaugeDevice = class(CSimBaseDevice)
    ....
end;
constructor CSimBaseDevice.Create(aOwner: TComponent);
begin
    inherited Create(aOwner);
    { Instantiate CSimBaseDevice Internally-Used Objects }
    kdKWDData := CKWDData.Create(self);
    adAlarms := CAlarmData.Create;
    { Define Component Related Settings }
    ControlStyle := ControlStyle + [csOpaque];
    { Define Event Handlers }
end; {constructor CSimBaseDevice.Create}

constructor CSimGaugeDevice.Create(aOwner: TComponent);
begin
    inherited Create(aOwner);
    { Instantiate CSimGaugeDevice Internally-Used Objects }
    bmpBG := TBitmap.Create;
    bmpBuff := TBitmap.Create;
    ggsGauges := CGauges.Create(self);
    tdsDisplays := CTextDisplays.Create(self);
    kdKWDData := CKWDData.Create(self);
    adAlarms := CAlarmData.Create;
    idInterlocks := CInterlockData.Create;
    { Define Event Handlers }
    bmpBG.OnChange := BmpChanged;
end; {constructor CSimGaugeDevice.Create}

In the create method of CSimGaugeDevice I use the 'inherited Create' command.  I want to make sure that the chain of inherited calls is intact.  Will CSimGaugeDevice call CSimBaseDevice's Create method and will then CSimBaseDevice call TGraphicControl's Create method?

Second easy question:  My application will have to search and catalog all of the components derived from CSimBaseDevice.  Previously I was using the 'IS' operator to locate each indiviual component --

   if (X is CSimGaugeDevice) then X.Draw;
   if (X is CSimTextDevice) then X.Draw;

Now that I'm deriving from a base class, can I now locate all of the derived components via a simple

   if (X is CSimBaseDevice) then X.Draw;

I know the question is rather long-winded, but once you get through I'm sure you'll agree that the answers are relatively simple...more or less just Yes/No answers (though please don't limit yourself to such).  BTW, historically, I'm a very good grader.
0
Comment
Question by:mheacock
  • 12
  • 5
17 Comments
 
LVL 3

Author Comment

by:mheacock
ID: 1335313
A comment...

if I set the ControlStyle in CSimBaseDevice, I'm guessing I'll also have to set this in CSimGaugeDevice??

Looking again at my code...since CSimBaseDevice in the application, should I be performing the Creates for the objects that CSimBaseDevice holds??

I've created tonnes of classes before, but this is my first foray into designing a whole array of them derived from a single base class.

I'm going to increase the points to all I have left to take into account these extra questions.  This question will be an easy A for the answeree (260 pts.).
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335314
I meant to say:

"Since CSimBase device is not instantiated in the application...."
0
 
LVL 3

Accepted Solution

by:
sperling earned 80 total points
ID: 1335315
>In the create method of CSimGaugeDevice I use the 'inherited
>Create' command. I want to make sure that the chain of inherited
>calls is intact. Will CSimGaugeDevice call CSimBaseDevice's
>Create method and will then CSimBaseDevice call
>TGraphicControl's Create method?

Yes. "inherited" means scan my parents, find the closest match
and call that procedure.


>Now that I'm deriving from a base class, can I now locate all of
>the derived components via a simple
>  if (X is CSimBaseDevice) then X.Draw;

Yes. "Is" is true if X is of class CSimBaseDevice or any descendant class of CSimBaseDevice.

All classes "is" TObject...


if I set the ControlStyle in CSimBaseDevice, I'm guessing I'll also have to set this in CSimGaugeDevice??

Not necessarry if you wan't to keep the value. ControlStyle is initially set in the class which introduced it. As you always call the parent constructor first, anything you do in any constructor just modifes the settings the parent(s) have made.

>Looking again at my code...since CSimBaseDevice in the
>application, should I be performing the Creates for
>the objects that CSimBaseDevice holds??

Depends... If you introduce a new variable with the same name, both classes need to create them. If you reference the variable belonging to CSimBaseDevice, you should not create again.


type
  TAClass = class
  protected
    FObject  : TObject;
  public
  .
  .
  .

  TAnotherClass = class (TAClass)
  protected
// If you declare FObject here also, they are different variables
// and both must be created. If you do not declare FObject here,
// you should not create it in TAnotherClass.Create
    FObject  : TObject;
  public
  .
  .
 
General rule of thumb... Create contained objects in the constructor of the class which declared the object.


>I've created tonnes of classes before, but this is my first foray
>into designing a whole array of them derived from a single base
>class.

Have fun. Now you're getting object-oriented ;)

Take a look at e.g. the TField and its ancestors for an explanation of the concepts...


I think I answered all your questions... If not, let me know..

Regards,

Erik.


0
 
LVL 3

Author Comment

by:mheacock
ID: 1335316
I'll wait a few days before grading this so that I can add a few more points to it.

So, if I define "kwdData.CKWDData" in CSimBaseDevice I should "kwdData := CKWDData.Create" it in CSimBaseDevice.  How would the derived class CSimGaugeDevice refer to that variable?  I'm guessing "Parent.kwdData".

So even though I set ControlStyle in the base class, it will affect the derived components?  So when I use CSimGaugeDevice on a form, it will not flicker when I alter it (the reason I set ControlStyle in the first place)??

BTW, an excellent answer.  Also would you prefer to wait a week until I can increase this to 100 points or will 75 points suffice?
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335317
I was thinking that, just because I set the ControlStyle property in the parent, it will not affect the ControlStyle property of its children.  You can look at the sample Create code in my question for a reference of what I mean.  The only reason I'm harping on Control style is that it will make a difference for all other parent declarations.
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335318
That should read:

--So if I define "kwdData: CKWDData" in CSimBaseDevice.....--
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335319
I'm going to go have a look at TField now.  Thanks.
0
 
LVL 3

Expert Comment

by:sperling
ID: 1335320
>So, if I define "kwdData.CKWDData" in CSimBaseDevice I should
>"kwdData := CKWDData.Create" it in CSimBaseDevice. How would the >derived class CSimGaugeDevice refer to that variable? I'm >guessing "Parent.kwdData".

Nope. The Parent property of a control has nothing at all to do with the class and ancestors/descendants...

If kwdData is declared in the protected or public sections of CSimBaseDevice, you can refer to it "as is"
If kwdData is declared in the private section, you cannot refer to it at all, *unless* the descendant of CSimBaseDevice is declared and implemented in the same unit, in which case you can also refer to it "as is".

The AControl.Parent property is just a pointer to the control on which 'AControl' is located. if Edit1 is placed on Panel1, Edit1.Parent will point to Panel1. This has nothing to do with classes, inheritance and so on.

> So even though I set ControlStyle in the base class, it will
> affect the derived components? So when I use
Yes

> CSimGaugeDevice on a form, it will not flicker when I alter it
> (the reason I set ControlStyle in the first place)??
No

I'll work out a little sample which might explain some class/object/inheritance concepts... I think you've gotten a few concepts wrong... But not until Monday though...

Don't bother about increasing points... I answer questions here mostly for the fun of it.


Regards,

Erik.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 3

Author Comment

by:mheacock
ID: 1335321
Well, that was stupid of me.  I know all about private/protected/public/published.  I should have relaized the reson I couldn't access kdKWDData in CSimGaugeDevice was that it was declared in the private section of CSimBaseDevice.  This is clear now...cystal...or at least damn near translucent.

As for the ControlStyle thing.  I intially had a flickering problem with my components, so I set
      ControlStyle := ControlStyle + [csOpaque];
Your answer above seemed contradictory.  If I set the above statement in CSimBaseDevice.Create, will the ControlStyle property in CSimGaugeDevice be set similarly?  If so, then I will not need to reset it in CSimGaugeDevice.Create.

I'll await your answer on Monday before grading.  Thanks a lot though.
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335322
Adjusted points to 70
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335323
Adjusted points to 75
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335324
You better get cracking...I am catching up to you in points...of course when I grade this, it will help you to increase the lead.
  <*grin*>
0
 
LVL 3

Expert Comment

by:sperling
ID: 1335325

>Your answer above seemed contradictory. If I set the above
>statement in CSimBaseDevice.Create, will the
>ControlStyle property in CSimGaugeDevice be set similarly? If >so, then I will not need to reset it in CSimGaugeDevice.Create.

It's the *same* ControlStyle property. You never create an instance of CSimBaseDevice. You just have access to it's code and data because CSimGaugeDevice is an descendant of it.

When you e.g. set the Name of a TEdit in Object Inspector, the code for 'SetName' in TComponent is executed on the data in the actual TEdit instance.

Whenever you call any method of a class, delphi will pass a pointer to the allocated data for the instance along with the call. Have a look at any class in the ObjectBrowser, and look at just variables. Assume the data is presented using the same layout as it is organized in memory at run-time. All variables in an object is referenced as an offset relative to the address of the last variable in this list. When you read the ComponentState of any component, delphi calls the original TComponent.GetComponentState or something, passing a pointer to the end of the allocated memory for the object. TComponent doesn't bother what class it actually is, it just knows about the last few fields shown in the list, and how to access them based on the passed "End-Of-Data" pointer. Therefore, the code to read/write ComponentState only need to exist at one location in memory, and it need not know in what context is is being called. It just needs to read/modify the variable at offset -8 of the passed object pointer.

This is not *exactly* how it's implemented, but it's pretty close.

When you set ControlStyle of any class, the same code is executed and the same (relative) variable is modified.

A class corresponds to a type
An object corresponds to a variable

Difference from types/variables is that classes have functions associated with them, which implicitly works on data in the referenced object.


Hmmm..
Not sure I understand myself here... Anyway, let me know *how* unclear this is ;)

Regards,

Erik.


0
 
LVL 3

Expert Comment

by:sperling
ID: 1335326
Yeah, I've seen that...

I've got too much damned (paid) work to do...

Regards,

Erik.
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335327
> When you set ControlStyle of any class, the same code is executed and the same (relative) variable is modified.

I think it was a little unclear.  I'll try one last question before I grade this and move on to experimenting with it in code.

My take on the whole thing is that if I instantiate 10 objects of CSimGaugeDevice, each of them will have their own ControlStyle property to alter as they see fit.  Or let's say CSimBaseDevice contains a public member called nTest: Integer.  I could set nTest in each of the CSimGaugeDevice's to a different value and each instantiation would retain that value.  Right?  Just because CSimBaseDevice is an abstract class (or as close as we get to it in Delphi) doesn't mean that nTest is 'global' to all the CSimGaugeDevice instatiations.  Right?

This is how I've been thinking of it and how I've been coding it all weekend...but I haven't quite reached the testing stage...either I'm right in my assumption and all will be well or I'm in for a big big surprise and I'll have to redesign some stuff.
0
 
LVL 3

Expert Comment

by:sperling
ID: 1335328
>My take on the whole thing is that if I instantiate 10 objects >of CSimGaugeDevice, each of them will have their own >ControlStyle property to alter as they see fit.

Right.

And, whether you set ControlStyle in CSimGaugeDevice or CSimBaseDevice code, doesn't matter. ControlStyle is global to the class, but local to the instantiated object.


Regards,

Erik.
0
 
LVL 3

Author Comment

by:mheacock
ID: 1335329
Okay...just what I was thinking all weeekend...didn't make any sense any other way.  Thanks for the help.

I just wanted to redesign these classes so that it would make it easier in a month to add new classes...which will be done.  I should have had more foresight when I first designed them...but sometimes foresight is a lot of extra work, even if it does save time in the long run.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now