Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Using Interfaces to simplify my life

Posted on 2004-08-05
4
Medium Priority
?
356 Views
Last Modified: 2010-04-05
Hi all
I am still struggling to see how I can use Interfaces and their reference counting to simplify my life.

Suppose I have a class ThandyDate

The traditional object way requires me typing

var myHandyDate : ThandyDate;
begin
myHandyDate := ThandyDate.create;
.. do something with myHandyDate
myHandyDate.Free;
end;

whereas (if I understand it correctly), converting THandyDate to an interface IHandyDate will allow me to simplify this to

var myHandyDate : IhandyDate;
begin
.. do something with myHandyDate
end;

no constructor and no destructor calls, because of reference counting.

Is it that simple? and how can I convert my ThandyDate class below to an interface ?

(***************************************************************)
(*                  TdsHandyDate                               *)
(*                                                             *)
(*  Easy to use date with Year,Month,Day properties            *)
(***************************************************************)

 type
  TdsHandyDate = class(Tobject)

private
  fYear,fMonth,fDay : Word;
  fDate : TdateTime;
  procedure _setDateTime(newDateTime:TdateTime);
 public
  procedure Clear;
  procedure SetDate(const Year,Month,Day:word);
  property asDateTime : TdateTime read fDate write _setDateTime;
  property Year : Word read fYear;
  property Month : Word read fMonth;
  property Day : Word read fDay;

  end;

thanks
0
Comment
Question by:Mutley2003
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
4 Comments
 
LVL 1

Expert Comment

by:Extase
ID: 11733601
>>no constructor and no destructor calls, because of reference counting.

that's wrong, because you've to Create the object prior to interface querying.

some of the advantages of using interfaces:
1- implementing multiple inheritance.
2- procedure calling across modules.
3- object interactions in a distributed object model.

usually you've to declare the interface then implement it in other objects., objects that implements an interface should implement all of it's methods(interface methods).
however, only methods and properties are allowed in interface decalaration.
interface methods are abstract,. thus they're useless unless implemented by some objects.

in your case you may declare IhandyDate as follows(using only 2 methods as an example):
however you can add your other properties to IHandyDate but you hv to declare their Get and Set procedures then implement them in THandyDate following the same way.

type
  IHandyDate = interface
     procedure Clear;
     procedure SetDate(const Year,Month,Day:word);
  end;
  //as you can see there's no fields
  //also visibility specifiers and storage specifiers are not allowed.

 //then implement IHandyDate in THandyDate
 //TInterfacedObject is base class for Delphi classes that support interfaces
  THandyDate = class(TInterfacedObject, IHandyDate)
  public
    procedure Clear;
    procedure SetDate(const Year,Month,Day:word);
  end;

  procedure THandyDate.Clear;
  begin
  end;

  procedure SetDate(const Year,Month,Day:word);
  begin
  end;

  //now how could we use that interface;
  //1st Create a THandyDate object then query it for IHandyDate

  var
    ADate:THandyDate;
    IDate:IHandyDate;
   
    ADate:=THandyDate.Create;
    ADate.GetInterface(IHandyDate, IDate);//interface querying, IDate will contain nil if ADate does not support IHandyDate

   then you can use IDate to call methods implemented by THandyDate.
   
   
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 11734225
Actually, it can be a bit easier...

var
    Date:IHandyDate;
begin  
    IDate:=THandyDate.Create; // Create the interface object.
    IDate.Clear; // Use it...
    IDate := nil; // Free it...
end;

If you have defined IDate as a local variable (Part of a function or procedure) then Delphi's garbage collection will free it for you. However, don't always count on it since nasty errors could occur that way. For global interface variables, you will have to free them though. And also in some other cases the garbage collection won't notice certain interfaces that need to be freed.

Interfaces don't free you from the create/destroy actions. However, interfaces are more aware of when they should be freed. As long as at least one variable is looking at the object, it will not be freed. Furthermore, you cannot mix interfaces and classes that easily. If you have:
    ADate:THandyDate;
    IDate:IHandyDate;
Then some people are tempted to write:
    IDate := ADate;
But then if you assign Nil to IDate, the object is freed because the reference counter is out of sync. Thus the use of ADate after this will generate an exception. Also, if you use this:
   ADate.GetInterface(IHandyDate, IDate);
   ADate.Free;
Then you're in trouble again. IDate just doesn't know that the object has been destroyed thus if you assign nil to it, another exception will occur because it tries to decrease a non-existing reference counter...

Still, I love the use of interfaces. I often work with lists, dynamic arrays of interface and add/delete interfaces to this list. And I could remove items from this list even while some other function was still using the object. They would just be removed when they are not in use anymore. Objects would just be removed, passed around, added again, handled some more until nothing is using them anymore. Then it's freed.
And this special freeing mechanism does make life a lot simpler...
0
 
LVL 20

Accepted Solution

by:
Madshi earned 2000 total points
ID: 11741968
I'm also loving interfaces. Usually my units look like this:

----------------------------

unit Whatever;

interface

type
  IHandyDate = interface
    ...
  end;

function NewHandyDate : IHandyDate;

implementation

type
  TIHandyDate = class (TInterfacedObject, IHandyDate)
    ...
  end;

...

function NewHandyDate : IHandyDate;
begin
  result := TIHandyDate.Create(...);
end;

end.

----------------------------

As you can see, I'm usually completely hiding the class in the implementation section. This allows me do to this:

procedure bla;
begin
  NewHandyDate.Whatever;
end;

All in all I think it's safe to say that implementing interfaces is just a little bit more work than implementing classes, but interfaces are nicer to use, because you don't need to care about freeing them. And construction can be easily wrapped up in a function like "NewHandyDate".
0
 

Author Comment

by:Mutley2003
ID: 11750754

people

I just gotta give the points to Madshi on this .. that is SO COOL!!!!

"
procedure bla;
begin
  NewHandyDate.Whatever;
end;

....... but interfaces are nicer to use, because you don't need to care about freeing them. And construction can be easily wrapped up in a function like "NewHandyDate".
"


YEAH. So NO var declaration., NO CREATE, no FREE

So I can do

procedure bla2;
begin  
 with NewHandyDate do begin
  something;
  somethingelse;
 end; // end with
// NewHandyDate goes out of scope here and is freed (I hope)
end;

This is nice clean minimalist code.

GREAT!
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This course is ideal for IT System Administrators working with VMware vSphere and its associated products in their company infrastructure. This course teaches you how to install and maintain this virtualization technology to store data, prevent vuln…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses

722 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