1. Home
  2. Computing & Technology
  3. Delphi Programming
RTL referenceGlossary|Tips/Tricks|FREE App/VCL|Best'O'Net|Books|Link To
 
Creating Custom Delphi Components - Inside and Out
Page 5: On Constructors
 More of this Feature
• Page 1: About components
• Page 2: New...Component
• Page 3: On Fields
• Page 4: On Properties
• Page 6: On Destructors and Methods
• Page 7: On Events
• Page 8: Hiding data
• Page 9: Virtual functions and Abstract Classes
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• VCL Writing/Enhancing
• Custom Component Dev.
• OOP in Delphi
• Free Source Components

   Constructors and Destructors
The TLine component you just created showed the basics of component writing. However, there are two major issues to cover - constructors and destructors.

Suppose you use dynamic memory in your component. Without any constructors and destructors this would be very error-prone. You'd end up with code that looked like this:

var
  SomeObject: TSomething;
begin
  SomeObject := TSomething.Create;
  SomeObject.Init; // yuck!
  //... use the object now
  SomeObject.Squish; // yuck!
  SomeObject.Free;
end;

You should be able spot why this would be bad - what if you forget to call Init or Squish? You would end up with an exception or memory leak (bad news) and would look like a fool. Well, luckily, constructors and destructors can help here. Oh, carefully forget to notice that I actually used constructors and destructors in the above example ;-). It's kinda hard in Delphi to avoid them.

   Constructors
Constructors get called whenever you create an object. Their job is to set up the internals of the object (variables, pointers, dynamic memory, etc.) as appropriate. The constructor is used to ensure you have a valid object - it should do no more or less than this. If you find after calling a constructor you still need to call some Init function then you haven't written an appropriate constructor, and should change it.

All objects is Delphi have a standard constructor ("Create"), which they get from TObject. This can be used to create the object, like so:

 SomeObject := TThisClass.Create;

where TThisClass is SomeObject's type. You must do this with classes before using them or you will get an exception. When you use the constructor the object gets space allocated for it and can be used. What if you want to change this constructor? Well, you can do this quite easily.

Every constructor can get declared like a procedure, but with "constructor" replacing "procedure" in the declaration. Since every object has a "create" constructor available, why not modify this to suit your purposes? Here's an example:

type
  TSomething = class(TObject)
  public
    { Public declarations }
    constructor Create;
    // etc.
  end;

implementation

// and the actual constructor definition
constructor TSomething.Create;
begin
  inherited;
  // do whatever you need (allocate memory, initialise variables, etc.)
end;

The above is the simplest constructor you might think about. There's only one thing that needs discussing - "inherited".

Inheritance is a concept in object-oriented design where a class can be a base for other classes. An example might be a "creature" class, which you could use as a base for "cat" and "dog" classes. The cat and dog would get data and behaviour from the "creature" base class, such as moving, having legs, fur, and so on, and would change this to suit their own needs (such as adding "woof" behaviour for dogs). The first class from which others derive is called the "base class" (or "super-class") and the ones that inherit from it are called "derived classes" (or "sub-classes").

Since every class is a sub-class of TObject, they automatically get its properties, methods, events, etc. (a slight exaggeration, as you'll see later). This includes the standard constructors and destructors ("Create" and "Destroy"). Since we have added our own code for the TSomething constructor the other code won't get executed - if you create a TSomething then TSomething.Create will get called, not TObject.Create. This is bad, as the base class might be doing clever/important things. Using the "inherited" keyword lets you call the base class's same method. This works for any constructor/destructor/procedure/function ("method").

Note that constructors can have any name, and any parameters. You're not just limited to "Create" and "Destroy", so another potential constructor might look like this:

type
  TMyClass = class(TSomething)
  public
    constructor InitWithStuff(const x: String);
  end;

implementation

constructor TMyClass.InitWithStuff(const x: String);
begin
  inherited Create;
  // do something with your parameter "x"
end; 

I'll first of all point out the slight change to "inherited". By default, inherited wants to use a method in the base class with the same name and parameters. If there isn't one, you can specify the method manually, as I've done here. You can also pass in parameters - you could, for example, do:

 inherited SomeProcedure(x,y,z); 

Now then, the above code makes a sub-class of TSomething, called TMyClass. It now has another constructor called "InitWithStuff". This is NOT available in TSomething, as it has only been introduced in this new class. Note now that TMyClass has two constructors, not just one! You could create a TMyClass like this:

 someObject := TMyClass.InitWithStuff('hello');

As you'd expect, this uses the constructor "InitWithStuff" we've just added to this new class. However, remember that TMyClass still has the Create constructor. This constructor didn't magically disappear when we created the new class - it's a method of TSomething (from TObject), which means that it's a method of this new derived TMyClass as well. This means it's syntactically correct to create a TMyClass like this:

 someObject := TMyClass.Create;

However, this isn't such a good idea. If an object gives you a constructor you should use it! Because we are bypassing TMyClass's constructor (it really wants us to use InitWithStuff) and are instead using the base class's version (TSomething.Create) we could be creating problems (excuse the bad pun :-p). The object we want might be missing out on some vital work work it needs because we're not using the thing provided. This leads to an important tip:

It's usually best to use the same name for constructors for every derived class

You can have two constructors (or more) in one class. This means one potential way to get around the problem might be this:

type
  TMyClass = class(TSomething)
  public
    constructor Create;
    constructor InitWithStuff(const x: String);
  end;

implementation

constructor TMyClass.Create;
begin
  raise Exception.Create('You must use InitWithStuff to create a TMyClass');
end;

constructor TMyClass.InitWithStuff(const x: String);
begin
  inherited Create;
  // do whatever stuff you need now 
end;

This solution works, but it's a little silly. It prevents anyone from using Create as a constructor for TMyClass (or any classes that are derived from it and use "inherited") because they'll end up with an exception. However, it's easier just to name your object constructors consistently from base to sub classes (usually you can just stick with "Create", as it's a standard name).

   Question, Suggestions...
If you have any questions or comments to this (huge) article, please post them on the Delphi Programming Forum. Discuss!

Next page > On Destructors and Methods > Page 1, 2, 3, 4, 5, 6, 7, 8, 9

All graphics (if any) in this feature created by Zarko Gajic.

 More Delphi
· Learn another routine every day - RTL Quick Reference.
· Download free source code applications and components.
· Talk about Delphi Programming, real time.
· Link to the Delphi Programming site from your Web pages.
· Tutorials, articles, tech. tips by date: 2001|2000|1999|1998 or by TOPIC.
· NEXT ARTICLE: GDI Graphics In Delphi.
From simple lines to direct API calls: the ultimate tutorial to GDI graphics in Delphi. This tutorial will introduce you to some of the techniques in the GDI Delphi drawing. Look for: drawing lines and shapes, drawing pictures, flicker-free drawings, off-screen bitmaps, GDI drawings the API way...
 Stay informed with all new and interesting things about Delphi (for free).
Subscribe to the Newsletter
Name
Email

 Got some code to share? Got a question? Need some help?
Explore Delphi Programming
About.com Special Features

Holiday Central

What to eat, where to go, fun things to do and how to save money on the perfect gifts. More >

Family Tech Center

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. More >

  1. Home
  2. Computing & Technology
  3. Delphi Programming

©2009 About.com, a part of The New York Times Company.

All rights reserved.