Solved

Proper OOP? How?

Posted on 1997-08-21
7
157 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
[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
  • 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
Suggested Courses
Course of the Month9 days, 13 hours left to enroll

623 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