Solved

Proper OOP? How?

Posted on 1997-08-21
7
156 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
Industry Leaders: 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!

 
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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

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 this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

739 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