Chained Inheritance -- overriding and inherited

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.
LVL 3
mheacockAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mheacockAuthor Commented:
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
mheacockAuthor Commented:
I meant to say:

"Since CSimBase device is not instantiated in the application...."
0
sperlingCommented:
>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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

mheacockAuthor Commented:
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
mheacockAuthor Commented:
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
mheacockAuthor Commented:
That should read:

--So if I define "kwdData: CKWDData" in CSimBaseDevice.....--
0
mheacockAuthor Commented:
I'm going to go have a look at TField now.  Thanks.
0
sperlingCommented:
>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
mheacockAuthor Commented:
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
mheacockAuthor Commented:
Adjusted points to 70
0
mheacockAuthor Commented:
Adjusted points to 75
0
mheacockAuthor Commented:
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
sperlingCommented:

>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
sperlingCommented:
Yeah, I've seen that...

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

Regards,

Erik.
0
mheacockAuthor Commented:
> 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
sperlingCommented:
>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
mheacockAuthor Commented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.