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

x
?
Solved

Passing parameters to a class

Posted on 2004-09-01
14
Medium Priority
?
228 Views
Last Modified: 2010-04-05
I have a class that i made a while back and would like to adapt it so i can use it without always having to make changes to it.  The main sticking point is that it deals with files of records which i'd like to move outside of the class and be able to define the record structure in any other unit and pass the parameters to the class.

example:

In my class i have this defined:

type
    TRecordName = packed record
    {...record structure}
end;

type
    TClassName = class

    private

       X : File of TRecordName;
       Y : TRecordName;
       {...rest of class functions and procedures that work with X and Y}

end;

What i'd like to do is be able to define the TRecordName in any unit i want and pass the structure to the class so it can still do what it was designed to do with the file of records - that way it allows the class to be "independant" in that it can be used on any record structure i define.

Anyone got a way to do this?
0
Comment
Question by:winuser2000
[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
  • 6
  • 6
  • 2
14 Comments
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 11961472
Apparantly you seem to want Macro functionaality, just like C++ and Assembler are offering. Unfortunately Delphi doesn't support this.

The best way to make a generic class is by using very generic code. If you're working with classes, consider the use of interfaces to include more abstraction in your code. If you want to stick to records then you need untyped variables, but except for the Variant record there's just no way to do this. (Delphi does support untyped parameters in functions, though!) Best way to solve this then would be this:

type
    TClassName = class
    private
       X : File;
       Y : Pointer;
       RecordSize:Word;

Y would then be pointing to a record somewhere in memory. This record would be RecordSize bytes in size, which you can set by using SizeOf(TRecordName). When reading from/writing to the file you'd have to use BlockRead and BlockWrite but that should not be too big of a problem.
Furthermore, be aware that records that you write to disk can't contain pointers. And the standard string in Delphi is a pointer. (The shortstring isn't, though.)

But actually, Delphi already has a nice, generic filereader/writer type. It's called TFileStream and is part of the TStream collection in Delphi... And streams can work with any kind of data.
0
 

Author Comment

by:winuser2000
ID: 11961841
"Apparantly you seem to want Macro functionaality, just like C++ and Assembler are offering"

Sheesh, i hope not because i have no idea what it is.

What i was basically looking for was a way to seperate the record structure from the actual unit.

For example, i can define the record structure in another unit and everything works perfectly if i put the unit name in the uses clause of the implementation section (to avoid circular problems).  I just thought that i since the file structure is in another unit and all works, maybe i could just pass the structure to the class in the constructor section (pooer example: such as MyRec.Create(TRecordStructure))

Not possible?
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 11962366
I don't know how important the actual structure of the record is, but you could do something like this to handle a file of records of any length:

type
tMyClass=class
  constructor create(aRecordLen:integer);
  destructor destroy;
  procedure readrec;
private
  fRecLen:integer;
  fRec:pointer;
  fFile:file;
end;

constructor tMyClass.create(arecordLen:integer);
begin
  assign(fFile,'datafile.dat');
  reset(fFile,aRecordLen);
  getmem(fRec,aRecordLen);
  fRecLen:=aRecordLen;
end;

destructor tMyClass.destroy;
begin
  closefile(fFile);
  freemem(fRec,fRecLen);
end;

procedure tMyClass.readrec;
begin
  { load next record }
  blockread(fFile,fRec^,1);
end;


Pass the record length to the class. You may want to pass the file name, too.

You might be able to work it into a generic solution.
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.

 

Author Comment

by:winuser2000
ID: 11963346
ok, i made some changes using the ideas given and now i am trying to get the record data into Y - but am having trouble:

Example:

Declared in Unit 1
=============

type
   TRecordName = packed record
   {...record structure}
end;

type
   TClassName = class
        constructor create;
        destructor destroy; override;

   private

      X : File;
      Y : Pointer;
      Procedure Add(ABC : TRecordName);
      {...rest of class functions and procedures that work with X and Y}

end;

The problem is, how do i make Y equal to the ABC content so i can work with it?
0
 

Author Comment

by:winuser2000
ID: 11963417
forgot...

after

type
  TRecordName = packed record
  {...record structure}
end;

the rest is declared in unit 2
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 11963420
Try

with TRecordName(Y^) do ...

0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 11963450
Oops, try:


procedure Add(abc:trecord);
begin
  Y^:=ABC;
end;

0
 

Author Comment

by:winuser2000
ID: 11963461
but if i pass ABC which is a record in the ADD procedure, how do i get the contents of ABC into Y in the first place?

0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 11963477
You could make the add routine not need to know the record structure, assuming the class knows the record length:

Procedure Add(var aData);
begin
  move(aData,Y^,fRecLen);
end;

0
 

Author Comment

by:winuser2000
ID: 11963483
tried that and got "operator not applicible to this operand" error
0
 
LVL 7

Accepted Solution

by:
LRHGuy earned 1000 total points
ID: 11963548
Where did the error point? I just tried this, compiled with no error. You may need to set a compile option to allow extended syntax or open parameters...(I'm using D7)

procedure tMyClass.Add(aData: trec);
begin
  move(aData,fRec^,fRecLen);
end;
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 11963627
Or:

procedure Add(aData:trec);
begin
  trec(fRec^):=aData;
end;

works too...
0
 
LVL 17

Assisted Solution

by:Wim ten Brink
Wim ten Brink earned 1000 total points
ID: 11963639
The Add method must either have an untyped variable or a pointer to a record. A pointer would be the best option here, I think. (Because untyped variables might be stored on the stack, thus disappearing from memory once the Add() method is done...

Also keep in mind that you cannot use TRecordName anywhere in your class because you don't want to know what type it is. You want more abstraction. I don't think you should declare TRecordName in unit1 anymore either. Your class will have to deal with pointers only that point to a record of a fixed size. Your class won't be able to handle the data in any way that's in the record. All it can do is read it from file or write it to file. This is called abstraction, making the class more usable to manage different types of data but also making the class less able to handle the data.

This:
  Procedure Add(ABC : TRecordName);
must be:
  Procedure Add(ABC : Pointer);
or:
  Procedure Add(var ABC);
or:
  Procedure Add(const ABC);

But abstraction of data works much better with classes than records.

You might consider using a TFileStream instead of a File, btw. If you keep writing just one type of record to it, it will just maintain a "file of type" layout... I feel that you're trying to build some stream-type here, reinventing a wheel that's already spinning quite well...
0
 

Author Comment

by:winuser2000
ID: 11963776
ok, i think i'll give up on this idea - i'd prefer to keep the functionality of the class as it works well so far with my records.

gonna up the points and split them between you both for the help

thanks.
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

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

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Suggested Courses

705 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