Solved

Proper OOP? How?

Posted on 1997-08-21
7
148 Views
Last Modified: 2013-11-23
Sorry about the title, couldn't think of anything better!

I have an app that responds to commands with data on the serial port.  I have a set of command objects that correspond to real commands.  Each one has a LoadFromStream method that gets the data from the serial port decoder (it does unencrypting and checksums etc).

Each command object is descended from TCustomCommand which has an abstract virtual LoadFromStream method.

I want to read the first byte of the stream which designates the command type, then create a command object:

var
  obj : TCustomCommand;
  Com : Byte;
begin
  S.Read(Com,1);
  case Com of
     1 : Obj:=TCommand1.Create;
     2 : Obj:=TCommand2.Create;
    etc.
  end;
  If Assigned(Obj) then
    Obj.LoadFromStream(S);

Now there's the tricky bit....the last line.  Does TCommand1.LoadFromStream get called?  Or does the compiler link to the declared object - ie TCustomCommand.LoadFromStream?

Can I use (Obj as Obj.ClassType).LoadFromStream?

None of the above attempts acutally compile and run.  Every time it tries to call an abstract method (ie TCustomCommand.LoadFromStream) or with Obj as Obj.ClassType it tries to call TObject.LoadFromStream at compile time, and fails cos TObject doesn't have the method.

HELP!!!!
This must be possible - it's one of the great niceties of OOP, isn't it?
  S.Read(
0
Comment
Question by:bcrotaz
  • 3
  • 3
7 Comments
 
LVL 3

Expert Comment

by:mirek071497
ID: 1342074
Tell me how You declare classes, or more abaut you'r code.

I Think so this must be as in my example then you can call Obj.LoadFromStream(..);

 TCustomCommand = class
  ....
  procedure LoadFromStream(..); virtual; abstract;
  ...
  end;

  TCommand1 = class(TCustomCommand)
  ...
  procedure LoadFromStream(...); override;
  ...
  end;

  of course LoadFromStream can be in private or protected only if you call this within module. For the first time try this procedure in public.
0
 
LVL 2

Expert Comment

by:icampbe1
ID: 1342075
The quickest way with your current setup would be to CASE again.

ie. at the end, do:

IF Obj <> NIL THEN
CASE Com OF
  1:  TCommand1(Obj).LoadFromStream(S);
  2:  TCommand2(Obj).LoadFromStream(S);
  etc..
END;
0
 
LVL 1

Author Comment

by:bcrotaz
ID: 1342076
case seems messy.
I have two procedures now. one works, the other doesn't....

Procedure 1
var
  Obj: TCustomCommand
begin
  case com of
     1 : Obj:=TCommand1.Create;
     2 : Obj:=TCommand2.Create;   etc
  end;
  Obj.LoadFromStream(S);
end;

That works.  The correct descendant method is called.

However, compare to this:

As above, but instead of last line:
DoLoad(Obj);


procedure DoLoad(Obj: TCustomCommand);
begin
  Obj.LoadFromStream(S);
end;

This one calls TCustomCommand.LoadFromStream;
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 1

Author Comment

by:bcrotaz
ID: 1342077
It must be possible to do this by OOP methods - I shouldn't have to iterate through all my object types to find which one I have...
0
 
LVL 3

Accepted Solution

by:
mirek071497 earned 100 total points
ID: 1342078
As i write some day's ago you probably mad mistake in setting procedures to protected statement.

This example works - this is OOP and must works (i was tested this)

type
  TAbstractClass = class
    procedure   LoadFStream; virtual; abstract;
  end;

  TTestClass1 = class( TAbstractClass )
    procedure   LoadFStream; override;
  end;

  TTestClass2 = class( TAbstractClass )
    procedure   LoadFStream; override;
  end;

implementation

procedure TTestClass1.LoadFStream;
begin
  ShowMessage( 'Test Class 1' );
end;

procedure TTestClass2.LoadFStream;
begin
  ShowMessage( 'Test Class 2' );
end;

procedure DoLoad( cc : TAbstractClass );
begin
  cc.LoadFStream;
end;

{ on form i create 2 buttons }

procedure TForm1.Button1Click(Sender: TObject);
var
  t1, t2 : TAbstractClass;
begin
  t1 := TTestClass1.Create;
  t2 := TTestClass2.Create;
  t1.LoadFStream;
  t2.LoadFSTream;
  t1.Free;
  t2.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  t1, t2 : TAbstractClass;
begin
  t1 := TTestClass1.Create;
  t2 := TTestClass2.Create;
  DoLoad( t1 );
  DoLoad( t2 );
  t1.Free;
  t2.Free;
end;

All procedures call good class - try !

but when Abstract class have constructor in public and next classes have constructor in protected then if you use them from other unit you have big problem. When you call TTestClass1.Create you call TAbstractClass.Create because procedures in protected statement is invisible in other units.

0
 
LVL 3

Expert Comment

by:mirek071497
ID: 1342079
Hi
Do you understand my answer ?
Do you need any help ?
0
 
LVL 1

Author Comment

by:bcrotaz
ID: 1342080
Thanks.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
automatically logging in via bde delphi 3 69
delphi custom sort exception 6 135
delphi parse string to params 3 99
Delphi: Connect to running MS Outlook 4 48
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
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…
Internet Business Fax to Email Made Easy - With  eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, f…
Many functions in Excel can make decisions. The most simple of these is the IF function: it returns a value depending on whether a condition you describe is true or false. Once you get the hang of using the IF function, you will find it easier to us…

910 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

22 Experts available now in Live!

Get 1:1 Help Now