Dynamic objects in delphi [closed] - delphi

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I know dynamic objects are objects created during run time. I have to make use of dynamic objects for a project, but not quite sure what to do. I'm not too sure what dynamic objects actually are except for the definition and for example once a button is clicked a panel is created, but this isn't exactly what is wanted from me. It is supposed to be more complex and meaningful.
What are other examples of dynamic objects and when or why would you use it?

Any instance of a class created at runtime in your code, and freed when you no longer need them. This happens all the time for classes that aren't visual components and can't just be dropped on a form.
Basic examples are things like TStringList for working with strings or text files, TStream descendants like TFileStream or TResourceStream, threads using TThread, generic lists such as TList<T>, and many other classes.
For instance, to work with a text file, an example of a dynamically created TStringList could be as follows:
var
SL: TStringList;
begin
SL := TStringList.Create;
try
SL.LoadFromFile('C:\Temp\MyFile.txt');
SL[0] := 'I changed this line.';
SL.SaveToFile('C:\Temp\MyFile.txt');
finally
SL.Free;
end;
end;

This sounds like a class project, and you don't seem to understand some of the terminology involved.
Just to generalize on this a little bit, in Delphi, instances of ANY class you define need to be created dynamically. This contrasts with records, which can be declared statically as variables as well as allocated dynamically.
In both cases (classes and records), when you create an instance dynamically, the memory for them is allocated from the heap, rather than the stack (where local vars are created). But the syntax is different in each case.
In Delphi, this contrasts sharply with C++, because C++ classes are basically structs (like Delphi records) with some embellishments, meaning that you can declare instances of classes in C++ as member variables where their memory is allocated on the stack in the same way you can declare instances of structs, as well as records in Pascal.
But this doesn't work in Delphi, even though the syntax looks the same. That's because in Delphi, the variables referring to classes are really pointers, like in C++, but they're automatically dereferenced, so they look syntactically as if they're just instances rather than a pointer-to-an-instance.
In Delphi, if you're working with a class, you MUST create it dynamically (by calling TMyObj.Create(...)). Thus, every class has a constructor associated with it; if you don't define one, the default TObject.Create constructor is called. (This is again different than in C++ where a default constructor will be created for you by the compiler for any class that needs one and it's not defined.)
I'll repeat this again so you're clear about it. Anything defined like THIS in Delphi:
type
Twhatever = class
is equivalent to this:
type
Twhatever = class( TObject )
and absolutely MUST be created dynamically in your code like this:
var
xyz : Twhatever; // xyz is really a pointer here! It's NOT an "instance"
begin
xyz := Twhatever.Create(); // you need to create an instance using the Create() method
try
// do some stuff
finally
xyz.Free;
end;
You cannot NOT use xyz without first creating an instance of it via it's .Create method.

Related

How to pass a list of objects to a function, which expects a list of objects which implement an interface?

tl;dr:
Trying to pass a list of objects to a function, which expects list of objects implementing an interface. Said objects implement that interface. Compiler will not allow it.
Looking for an alternative workaround or my mistake.
The setup
I did not use the actual code, and that should not matter IMO. Seems like a conceptional problem to me.
The class TObjectWithInterface implements the interface ISomeInterface and extends the class TCustomInterfacedObject, which simply works around the reference counting of IInterface as given in the documentation.
TObjectWithInterface = class(TCustomInterfacedObject, ISomeInterface)
If have a procedure which takes a list of objects implementing that interface:
procedure SomeFunction(List: TList<ISomeInterface>)
The issue
Inside of a function of TObjectWithInterface, I try to call that function, using a list of objects of TObjectWithInterface:
procedure TObjectWithInterface.DoTheStuff(ListOfObjects: TList<TObjectWithInterface>)
begin
// ...
SomeFunction(ListOfObjects); // <-- Compiler error: Incompatible types
// ...
end;
The compiler tells me the following:
E2010: Incompatible types: 'System.Generics.Collections.TList' and 'System.Generics.Collections.TList'
The dumb workaround
I really dislike my current workaround, which consists of creating a new list and type casting each TObjectWithInterface to ISomeInterface:
procedure TObjectWithInterface.DoTheStuff(ListOfObjects: TList<TObjectWithInterface>)
var
ListOfInterfaceObjects: TList<ISomeInterface>;
begin
// ...
ListOfInterfaceObjects := TList<ISomeInterface>.Create;
for var Object in ListOfObjects do
ListOfInterfaceObjects.Add(Objects as ISomeInterface);
SomeFunction(ListOfInterfaceObjects)
// ...
end;
This seems very hacky to me. I may have done something stupid, or do not understand something correctly, as this is the first time, that I am trying to use Interfaces in Delphi. Please don't be mad.
Either way, I hope someone can point out my mistake or, if this is a language limitation, has an alternative workaround.
Your "workaround" to copy the list of objects into a separate list of interfaces is actually the correct and proper solution. You can't use a TList<X> where a TList<Y> is expected, they are different and unrelated types. Just because you are disabling reference counting on the interfaces doesn't change the memory layout of the objects in relation to their interfaces, so you still have to pass around proper memory pointers, which means performing necessary conversions from one to the other.

Delphi. Clone an object [duplicate]

This question already has answers here:
How to copy the properties of one class instance to another instance of the same class?
(3 answers)
Closed 5 years ago.
Is it possible to clone an object with another reference?
Here is an example what i'm trying to do: I have a TLabel named Label1. Now I want to create a Label2, equals Label1, able to be changed without reflect each other.
Ps: I'm using TLabel as an example, I want to copy any object in another instance.
In the code below, I've tried changing the name, but the reference still the same, when a change one of them the other changes too.
var
cloneOfLabel1: TLabel;
begin
Label1.Caption := 'label 1';
cloneOfLabel1 := Label1;
cloneOfLabel1.Name := 'label2';
cloneOfLabel1.Caption := 'label 2';
cloneOfLabel1.Left := 0;
cloneOfLabel1.Top := Label1.Top+100;
That's possible to write Clone function for TComponent descendants:
function CloneComponent(aSource: TComponent): TComponent;
var mem: TMemoryStream;
begin
mem := TMemoryStream.Create;
try
mem.WriteComponent(aSource);
mem.Seek(0,soFromBeginning);
Result := mem.ReadComponent(nil);
finally
mem.free;
end;
end;
Note that only published properties gets copied that way and also some data which component saves through DefineProperties. Integers, floats, strings, enumerations and sets are cloned fine, but there could be problems with references: streaming system is designed for saving to file and reading from there, so no memory adresses get transfered, instead rather complicated actions are made to convert them into string paths including component owner and names. Usually you need to stream all the structure and only then some inner relationships would be saved.
If you are designer of classes which should be cloned, then overriding Assign method seems like more robust solution.
Good thing of this TComponent streaming solution is: you're able to clone some arbitrary component without knowing ahead, what class it is. For example, make a list of various components or some more complex structure and then get the full copy of each of them.
In your code, you are doing this:
cloneOfLabel1 := Label1;
However, this is merely acquiring a copy of its pointer, so it will still reference the original. It will not make a copy.
The closest you can get stems from TPersistent.Assign(), which needs to be implemented to actually copy the properties over. TLabel does not implement Assign, and so you cannot use it to create a clone either.
The answer is that you cannot arbitrarily clone objects, unless it inherits from TPersistent and implements Assign. And even then, you are at the mercy of the Assign procedure, so it will only copy those properties it was designed to copy. Name is certainly not one of those, especially since it's impossible to have two components with the same name. In fact, even if you do set a unique name to a cloned copy of a component, you cannot reference it by that, because it was created in run-time. Only design-time components can be referenced directly by their name.
On a side note, records can (by nature) be copied by using a simple :=, because records are value types instead of classes. However, I'm sure based on your example, that records are out of the question.

Class doesn't work when defined as a global variable in delphi

I created a simple class to explain my problem:
ttest =class
private
val:boolean;
published
function get:boolean;
end;
...
function ttest.get: boolean;
begin
val:=not val;
result:=val;
end;
Now if I declare a local ttest variable and call my_var.get; then everything works, but if I declare it as a global variable then it can't access the val field anymore, it shows an error message which says "Access violation...".
I read some articles about classes in Delphi but still can't find my mistake.
You've neglected to instantiate the class.
Global class-reference variables are initialized to nil, whereas local variables are not initialized at all. The local variable has a value determined by whatever happened to be on the stack at the time you called your function, and your program is interpreting that value as though it were a TTest reference even though it's really not. Your program then reads the value at that memory address to get the value that would represent the val field.
The only reason your code appears to work with a non-global variable is luck. Whether it's good luck or bad is another matter. (Good luck, since your code appeared to work, and working code is always nice. Bad luck, since you'd have been alerted to your mistake earlier if your code had crashed.)
Instantiate a class before you use references to it.
x := TTest.Create;
Now you can access fields, methods, and properties of the object via the x variable.
You should have gotten a compiler warning when you attempted to use a local variable without assigning a value to it first. Although they're just warnings, and your program will still run, never ignore a warning or even a hint. When the compiler bothers to complain about something, it's usually right.
In Delphi object variables are always pointers. Before you can use the variable you need to initialize it with a reference to an object. The most common way to do that is to create a new object of the particular class.
procedure Foo;
var
Obj: TObject;
begin
Obj := TObject.Create;
try
// Do stuff with Obj
finally
Obj.Free;
end;
end;
In this case Obj starts out as an uninitialized pointer (it will point to random memory). It is only after we assign the newly created TObject that Obj is a valid object reference.
In Delphi there is no automatic garbage collection for objects, so you always need to call free on them when you are done using them. If you declare a global or local object variable, you can initialize it the special initialization section of the unit and free the object in the finalization section.
unit myunit;
interface
var
Obj: TObject;
implementation
initialization
Obj := TObject.Create;
finalization
Obj.Free;
end.
Variables declared in the interface section are globally visible, variables declared in the implementation section are only visible inside the unit. It should be noted that declaring a global object variable means that any unit can overwrite the variable with a reference to a new object without freeing the existing object first. This would cause a memory leak as again there is no automatic garbage collection.
A delphi class is basically just a description, not the object itself. You describe the properties and methods the final object should have. And the missing piece of the puzzle is that you havent really told Delphi to create an object from your class.
This is done by calling the constructor:
mMyInstance:=TTest.Create;
The constructor takes the class description and builds an object instance for you in memory. It returns a pointer to the object which you must store in a variable (myInstance in the above example) of the same type.
Reading your question, I suspect you want to create an object that is "always there", a bit like the printer object. This is easy to do, but just like the printer object - you must include that unit before you can access the object. I think Anders E. Andersen above has shown how most people would initialize an object from a unit centric point of view.
If you want the object to be reachable from another unit, say your mainform or any other unit, first add "myunit" to the uses list. Then to make it visible you add a function, like this:
function test:ttest;
Begin
result:=obj;
end;
And remember to add "function test:TTest" to the interface section of the unit. Then you can use the object from another unit as such:
myUnit.test.get;
But be warned! This is pretty old school programming, and you run the risk of your unit being released (which calls finalization and thus destroys your object) before the other units are done with it. Thus you risk calling a function in an object which no longer exists in memory - causing a spectacular access violation when your program closes.
If you want to learn Delphi properly, head over to Delphi Basics and read up on the basic principles. It takes a while to learn a new language but you will soon get the hang of it.
Good luck!

Delphi Unit local variables - how to make each instance unique?

In the unit below I have a variable declared in the IMPLEMENTATION section - local to the unit. I also have a procedure, declared in the TYPE section which takes an argument and assigns that argument to the local variable in question. Each instance of this TFrame gets passed a unique variable via passMeTheVar.
What I want it to do is for each instance of the frame to keep its own version of that variable, different from the others, and use that to define how it operates. What seems to be happening, however, is that all instances are using the same value, even if I explicitly pass each instance a different variable.
ie:
Unit FlexibleUnit;
interface
uses
//the uses stuff
type
TFlexibleUnit=class(TFrame)
//declarations including
procedure makeThisInstanceX(passMeTheVar:integer);
private
//
public
//
end;
implementation
uses //the uses
var myLocalVar;
procedure makeThisInstanceX(passMeTheVar:integer);
begin
myLocalVar:=passMeTheVar;
end;
//other procedures using myLocalVar
//etc to the
end;
Now somewhere in another Form I've dropped this Frame onto the Design pane, sometimes two of these frames on one Form, and have it declared in the proper places, etc. Each is unique in that :
ThisFlexibleUnit : TFlexibleUnit;
ThatFlexibleUnit : TFlexibleUnit;
and when I do a:
ThisFlexibleUnit.makeThisInstanceX(var1); //want to behave in way "var1"
ThatFlexibleUnit.makeThisInstanceX(var2); //want to behave in way "var2"
it seems that they both share the same variable "myLocalVar".
Am I doing this wrong, in principle? If this is the correct method then it's a matter of debugging what I have (which is too huge to post) but if this is not correct in principle then is there a way to do what I am suggesting?
EDIT:
Ok, so the lesson learned here is that the class definition is just that. Many classes can go in one unit and all instances of all classes in the Type section share the implementation section of the unit.
myLocalVar is a global variable, but only visible within the unit.
A local variable would be in a procedure/function, like
procedure makeThisInstanceX(passMeTheVar: integer);
var
myLocalVar: Integer;
begin
myLocalVar := passMeTheVar;
end;
if you want an instance variable, that is each frame has its own copy, put it in the class:
type
TFlexibleUnit = class(TFrame)
procedure makeThisInstanceX(passMeTheVar:integer);
private
myLocalVar: Integer;
...
end;
You are calling the makeThisInstanceX method as a class (static) method rather than creating an instance of the class and calling it as an object method. Take a look at this reference:
http://oreilly.com/catalog/delphi/chapter/ch02.html
frame / unit / class / control
I applaud your heroic attempt to better the code. However, judging by your questions and comments I regret to inform you that your understanding is very limited.
A frame is not a unit which is not a class. A frame is a class but not every class is a frame. A frame is a control but not every control is a frame. Units have interface and implementation (and initialization and finalization) sections. Classes have private and public (and protected and published) parts.
I did not put the last paragraph in to try to teach but to allow you to gauge your understanding level. A Delphi developer ought to have no problem with the paragraph. I'm not trying to make you feel bad or to show off - just trying to help. Perhaps Stack Overflow is not the right tool for you at this time.
As somebody just learning Delphi for the first time, I might be confused by some of the seemingly redundant features. But the product has a long history and each addition made sense at the time it was added. It was also easier to learn when you only had to learn it a piece at a time.

What Design Patterns do you implement in common Delphi programming? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
What Design Patterns do you implement in common Delphi programming? What patterns are easier to adapt in Delphi programming? (Every language is excellent in different fields, so what patterns are likely to be very strong structures when using Delphi?)
I would be glad, if you could tell about some changes in design patterns for Delphi 2009 / 2010 (since those support generics, and RTTI in 2010).
There are many articles out there in the wild Internet, but they doesn't discuss the everyday usability and changes in patterns. (Most of them just discuss changes in language specifics, architecture).
Only a minority of the Delphi developers knows that every Delphi developer uses a Factory pattern (delphi.about.com has an example in "regular" Delphi), but then implemented using virtual Create constructors.
So: time to shed some light on that :-)
Virtual constructors are to classes like virtual methods are like object instances.
The whole idea of the factory pattern is that you decouple the logic that determines what kind (in this case "class") of thing (in this case "object instance") to create from the actual creation.
It works like this using virtual Create constructors:
TComponent has a virtual Create constructor so, which can be overridden by any descending class:
type
TComponent = class(TPersistent, ...)
constructor Create(AOwner: TComponent); virtual;
...
end;
For instance the TDirectoryListBox.Create constructor overrides it:
type
TDirectoryListBox = class(...)
constructor Create(AOwner: TComponent); override;
...
end;
You can store a class reference (the class analogy to an object instance reference) in a variable of type 'class type'. For component classes, there is a predefined type TComponentClass in the Classes unit:
type
TComponentClass = class of TComponent;
When you have a variable (or parameter) of type TComponentClass, you can do polymorphic construction, which is very very similar to the factory pattern:
var
ClassToCreate: TComponentClass;
...
procedure SomeMethodInSomeUnit;
begin
ClassToCreate := TButton;
end;
...
procedure AnotherMethodInAnotherUnit;
var
CreatedComponent: TComponent;
begin
CreatedComponent := ClassToCreate.Create(Application);
...
end;
The Delphi RTL uses this for instance here:
Result := TComponentClass(FindClass(ReadStr)).Create(nil);
and here:
// create another instance of this kind of grid
SubGrid := TCustomDBGrid(TComponentClass(Self.ClassType).Create(Self));
The first use in the Delphi RTL is how the whole creation process works of forms, datamodules, frames and components that are being read from a DFM file.
The form (datamodule/frame/...) classes actually have a (published) list of components that are on the form (datamodule/frame/...). That list includes for each component the instance name and the class reference.
When reading the DFM files, the Delphi RTL then:
finds about the components instance name,
uses that name to find the underlying class reference,
then uses the class reference to dynamically create the correct object
A regular Delphi developer usually never sees that happen, but without it, the whole Delphi RAD experience would not exist.
Allen Bauer (the Chief Scientist at Embarcadero), wrote a short blog article about this topic as well.
There is also a SO question about where virtual constructors are being used.
Let me know if that was enough light on the virtual Create constructor topic :-)
--jeroen
You can find an excellent article by Marco Cantu on the equivalence of GOF patterns and Delphi idioms. I remember attending his Borcon session on the subject, it was excellent.
One main idea to remember is that design patterns are needed to supplement shortcomings of the language/framework. And if you have a native idiom, you don't need to reinvent the wheel and implement the whole GOF shebang, just learn to recognize it and name it (as Jeroen did with his superb explanation on the Factory).
I use frequently following patterns:
Command
Visitor
Table Data Gateway
Observer
Adapter
Singleton (with many care!)
Abstract Factory
Factory Method
State
Dependency Injection in all of his form
Facade
Service Locator
Separated Interface
I frequently uses the following patterns:
Observer in MVC
Singlton
Template Method
State
Non-OOP programming (some call it Structured programming) is very common with Delphi programmers. It is very simple: You create a function that does something, and it is not related to a record/object-like data structure. Example: IntToStr()
Delphi does this very well, because encapsulation is delivered using interface/implementation sections, and because the resulting machine code is extremely efficient. When compiling, it also supports optimizations for that, for instance, if you have a typed constant in your interface section, and the program is fully compiled - if you then change the value of that constant, the unit is not recompiled, only the constant changes. This is not really necessary in a daily work, but it is an example of how Delphi works.
An ordinary Unit behaves like a singleton. You can't use OOP-techniques like inheritance and polymorfism though, but that might be a good thing :)
I generally think that Delphi makes it too easy to avoid sound oop design. That is nice for RAD, but you need to know which pitfalls to avoid if you want a flixible and maintainable code. Eg the public visibility for the components you add to the forms, the global Form1 variable of type TForm1 (instead of manually managed lifetime and a base class as type) and the lack of seperation between GUI and business logic. Just to mention some issues.

Resources