Why is this code working and how is Delphi instantiating a class in this case? - class

I'm doing the Delphi track at exercism, and following how Delphi generates code for a form, answered one of the basic questions like this:
unit uLeap;
interface
type
TSYear = class
public
{ public declarations here }
function isLeap(y: integer): boolean;
end;
var
TYear: TSYear;
implementation
function TSYear.isLeap(y: integer): boolean;
begin
result := ((y mod 4) = 0) and (((y mod 400) = 0) or ((y mod 100) <> 0));
end;
end.
the code compiles without a single complaint, I can run it step by step, and the "isLeap" function is called from another unit several times this way:
procedure YearTest.year_divisible_by_4_not_divisible_by_100_leap_year;
begin
assert.IsTrue(TYear.IsLeap(1996), 'Expected ''true'', 1996 is a leap year.');
end;
...
I've never explicitly created the instance of the class, but it seems as if Delphi is doing it somewhere, maybe when declaring TYear? Is that a valid way?
Despite passing all the tests the code was rejected because it isn't done the conventional way. I'll surely end up doing it differently to have it accepted, but, besides the bad naming, why is this working? Would this code cause problems somewhere I can't see in this simple example?

I've never explicitly created the instance of the class, but it seems as if Delphi is doing it somewhere, maybe when declaring TYear?
No, Delphi is NOT automatically creating an instance of you. When you declare a variable of a class type, it is simply a pointer variable that can be made to point at a valid instance. But you must always create this instance yourself, and save the pointer in the variable:
SYear := TSYear.Create; // create a `TSYear` object and save its address in `SYear`
Is that a valid way?
No.
[W]hy is this working?
Because you are lucky: The isLeap function doesn't access any fields on the class instance.
Would this code cause problems somewhere I can't see in this simple example?
If the function had been using any fields in the class instance, you would have ended up with an AV if lucky and memory corruption if unlucky.
The solution is either to create an instance and use it:
SYear := TSYear.Create;
try
ShowMessage(BoolToStr(SYear.IsLeap(2000), True));
finally
SYear.Free;
end;
Or, since you clearly don't need any instance variables to determine if a year is a leap year or not, it is better to make this a class method:
type
TSYear = class
public
class function IsLeap(AYear: Integer): Boolean; static;
end;
This way, it can be called without any class instance: TSYear.IsLeap(2000). Notice that TSYear is the class (type) name, not a variable of this type.
Please see the documentation for a great conceptual introduction to all these concepts.

Related

In Delphi, how do I make a type passable only between functions/methods of a class [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I currently have the following code;
interface
{...}
type
TMyRecord = record
List : TShellList;
Tree : TShellTree;
Image : TImage;
end;
TSDIAppForm = class(TForm)
{ Published declarations }
private
function GetChildren(Sheet : TTabSheet) : TMyRecord;
public
{ Public declarations }
end;
As I understand it this means that TMyRecord is a global type visible to the whole program. The type only needs to be visible within the class, although objects of the type do need to be passed and returned as parameters to between "private" functions/procedures of the class. How can I do that? I can't declare the type under the "private" part of the class interface, and if I declare it in the implements then I don't believe it is visible to be used in the interface function prototypes. Also, I think implements/interface relate more to visibility within the unit than the class. Do I need to declare theGetChildren() function in some other way?
As noted in other answers, in versions of Delphi that support nested types you can simply declare the type within the required scope and visibility.
For older versions of Delphi you can achieve a similar outcome by using an untyped var parameter to avoid having to reference the 'private type' in the interface section of your unit:
TSDIAppForm = class(TForm)
..
procedure GetChildren(Sheet : TTabSheet; var aRecord);
..
end;
For convenience and declarative type enforcement in the implementation of the method you can use an absolute declaration to create a local variable to act as placeholder for the untyped parameter:
procedure TSDIAppForm.GetChildren( Sheet : TTabSheet;
var aRecord);
var
result: TMyRecord absolute aRecord;
begin
result.List := ...;
// etc
end;
In this case, since the function has no direct return value and uses the var param in a directly analagous way you might choose to use the name result, as illustrated. Or of course you can use any other name for the local variable you prefer.
In use, you would simply call this method as normal with an appropriate variable in the var param:
var
myRec: TMyRecord;
begin
..
sdiForm.GetChildren(someSheet, myRec);
..
end;
In this way, you can keep a type which is an implementation detail truly confined to the implementation section of your unit.
NOTE: This technique can also be useful in situations where typed var parameters might otherwise cause the compiler to complain about 'formal var parameter types not matching'.
You should of course always consider carefully whether they are the right approach. Not least because whenever you use untyped parameters of course you take on a greater responsibility for ensuring type safety in your code. The potential for abuse should be obvious, but they sometimes offer advantages as well (as in this case, removing entirely a type from the interface section that is arguably most properly entirely confined to the implementation section).
They can also be a useful tool to keep in mind if you create code that you might wish to make available to users of older versions of Delphi where private types etc are not available.
Per Uwe, just declare in private section. Tested in XE8. The following works
TSDIAppForm = class(TForm)
private
type
TMyRecord = record
List : TShellList;
Tree : TShellTree;
Image : TImage;
end;
function GetChildren(Sheet : TTabSheet) : TMyRecord;
public
{ Public declarations }
end;

Delphi Classes: Property vs Get/Set methods

So I'm kinda new to OO programming. Delphi has properties which are intended to be a "more elegant" way to acess class data than getters/setters (read it here usage of property vs getters/setters in business classes).
When should I use the fields directly and when should I use getters/setters inside the property? I'm gessing only when the data needs to be manipulated, but I'm not sure.
Edit:
Is it wrong to omit a setter that does nothing but return the value of the field itself?
property Field :integer read FField write FField;
Why properties?
For starters, a quick summary from the documentation on properties:
A property, like a field, defines an attribute of an object. But while a field is merely a storage location whose contents can be examined and changed, a property associates specific actions with reading or modifying its data. Properties provide control over access to an object's attributes, and they allow attributes to be computed.
Why not only setter and getter?
Separation of storage and access can indeed be achieved by the use of just getters and setters, and leave the property be. That is true, but the question you link to originates from a language difference: Delphi does have properties, and the answers there already explain why to use them. The two most obvious reasons are (1) cleaner code and (2) assignment capability. I think this answer deals with it quite extensive already.
Furthermore, without the use of properties, getters and setters are always needed, where with properties they are not. Assume a setter implementation, but no getter: a property can directly read the field.
Class completion
When you just declare a property's name and its type, Delphi's class completion defaults to reading a private field and a private setter which sets the private field. Mind that this is just the default configuration, which you again can modify to your needs. When you fully specify the property declaration, class completion will comply and add a private field, a getter and/or setter as required for your declaration.
Properties without getter and setter
Is it wrong to omit a setter that does nothing but return the value of the field itself?
When a property has no getter nor setter and it just reads and writes the field, then you could conclude that there is no difference beside being consistent. But that is not the case. The field and the property have distinct names, and therefore possibly distinct meaning. Meaning that you can give. See Using properties instead of fields in class methods of the same unit is a bad practice?.
When to use a getter or setter?
... I'm gessing only when the data needs to be manipulated ...
Well, that is partly true. Manipulation is one of the many reasons. Consider a Price property of type String, and its private field FPrice:
Limitation: When the price needs to be equal or higher than zero,
Delegation: When FPrice is part of another field, or when it otherwise is beyond the responsibility of this class,
Verification: When the price may only have two decimals behind the comma,
Interpretation: When the price is entered in thousands, but should be stored in cents,
Effect: When the price has consequences for another field, for example rate or margin,
Activation: When an edit to the price requires immediate action, for example updating the GUI,
Conversion: When the price is entered in dollars but should be stored in yen,
Cancelation: When the price does not make sense, for example when it is entered in scientific notation.
Note that a Price property is quite rudimentary. Leaving its setter or getter for future implementation is very well possible. But imagine more advanced properties which cannot do without setter or getter:
A field that needs to be created before consulting:
function TMyObject.GetBarelyUsed: TRare;
begin
if FBarelyUsed = nil then
FBarelyUsed := TRare.Create(Self);
Result := FBarelyUsed;
end;
An item can be selected, but the item itself does not know what to do. Instead the owner does. Notice the complete absence of the private field in this case:
procedure TItem.SetSelected(Value: Boolean);
begin
if Value <> Selected then
begin
if Value then
Owner.Selection.Add(Self)
else
Owner.Selection.Remove(Self);
end;
end;
An image control, specialized in viewing your own image format. Assignment of the FileName property involves: checking the correct file extension, checking file existance, storing the file name in the private field, loading the file, adjusting the pictures' dimensions, or else undoing the previous assignment:
procedure TAwDxfImage.SetFileName(const Value: TFileName);
begin
if FFileName <> Value then
if SameText(ExtractFileExt(Value), '.' + SDxf) and
FileExists(Value) then
begin
FFileName := Value;
FGraphic.LoadFromFile(FFileName);
FGraphic.SetBounds(Width, Height);
end
else
begin
FFileName := '';
FGraphic.Clear;
end;
end;
Source: NLDelphi
In addition to #NGLN answer there is another use case for property getter/setter.
Accessing class instances through interface is only possible via instance methods. If you have to access property in such case you have to implement getter/setter methods.
type
IField = interface
function GetField: integer;
procedure SetField(value: integer);
property Field: integer read GetField write SetField;
end;
TField = class(TInterfacedObject, IField)
protected
FField: integer;
function GetField: integer;
procedure SetField(value: integer);
public
property Field: integer read GetField write SetField;
end;
var
f: IField;
x, n: integer;
...
f := TField.Create;
f.Field := 5;
f.SetField(6);
n := f.Field;
x := f.GetField;
Of course, depending whether you need only read or write access to that property you can omit setter or getter in your interface declaration.
Keep in mind that accessing instance through interface gives all interface implemented methods public visibility. That is why in above example you can call f.GetField despite it being declared protected (or even private).
What is unacceptable is to do this
TMyClass = class
private
public
Fubar :integer;
end;
the remainder of your examples are fine. I would be happy to receive code from you that reads like this
TMyClass = class
private
FFu : integer;
public
property Fu :integer read FFu write FFu;
end;
because I can confidently change it to
TMyClass = class
private
FFu : integer;
procedure SetFu(Value : Integer);
function GetBar() : string;
public
property Fu :integer read FFu write SetFu;
property Bar : String read GetBar;
end;
without breaking existing code.
I have a personal dislike of setters that do nothing
procedure TMyClass.SetFu(Value : Integer);
begin
FFu := Value;
end;
But in truth it is harmless.
Does that help?
This would be a valid reason or incentive for using a setter
procedure TMyClass.SetFu(Value : Integer);
begin
if FFu <> Value then begin
FFu := Value;
if Assigned(FAfterFooChanged) then
FAfterFooChanged(FFu);
end;
end;
not 'manipulation' as such ...

SIGSEGV when using interfaces

Please take a look at the following Free Pascal program.
type
IMyInterface = interface
end;
TMyClass = class(TInterfacedObject, IMyInterface)
end;
var
MyInstance: TMyClass;
procedure DoSomething(MyParameter: IMyInterface);
begin
end;
begin
MyInstance := TMyClass.Create;
DoSomething(MyInstance);
MyInstance.Free;
end.
The program crashes during the access to the destructor with a SIGSEGV when started from within the IDE (compiled with debug information). Why? It works when I use TInterfacedObject, TObject, or TMyClass as parameter type. It even works when I use the const keyword for said parameter. Can anyone explain this behavior? With a quick sideways glance to Java I would expect this to work.
Compiled with FreePascalCompiler 2.6.4, executed under Windows 7.
I cannot speak for FPC, but with Delphi it is a bad idea to mix interfaces and objects. In this case you have two solutions:
declare MyInstance as IMyInterface and remove the call to Free.
inherit TMyClass from TInterfacedPersistent.
To clarify what is actually happening: Creating the TMyClass instance and assigning it to MyInstance will keep the reference count to 0. When you pass it to DoSomething a cast to IMyInterface takes place and the reference counter increases. When DoSomething ends the reference counter decreases to 0 and the instance is freed. The following call to Free will free an already freed instance.
DoSomething expect a IMyInterface
when you pass MyInstance , it's make a counter control, so when the method DoSomething finish, MyInstance has a counter decrement.
the TMyClass is a TInterfacedObject, so when the counter = 0, then Object will be freed, so you don't need to call MyInstance.Free;
you can do:
DoSomething(TMyClass.Create);
Your Object uses Reference Counting, to free it you must decrement the reference count. An alternative is to use what's called CORBA interfaces.
In FPC object pascal mode a CORBA interface is a pure interface which does not derivates from IUnknown (in opposite to COM interfaces). If you add the compiler directive:
{$INTERFACES CORBA}
then you'll be able to use the .Free method, just like with any other TObject instance. Note that the name can be confusing since CORBA is a full cross-language specification (IDL), but here corba just means "not COM".
online reference:
http://www.freepascal.org/docs-html/ref/refse44.html#x98-1080007.6

what is the meaning of `Class of ` type declaration?

While going through one of my code, I am stuck on one statement which is as below.
TMyObjectClass = class of TMyObject;
I am a bit confused, and wondering what is the meaning of this statement.
As TMyObjectClass has no declaration above the statement.
and TMyObject is having declaration as below:
TMyObject = class(TObject)
private
//some private member declaration
Public
// some public variables
end;
So, my question is what is the meaning of the statement
TMyObjectClass = class of TMyObject;
and How TMyObjectClass works?
I am a bit new to Delphi, so please help me to get some idea about these type of declaration and there workarounds.
This is a Class Reference.
They are used to work with meta classes. The canonical example is the Delphi streaming framework which uses
TComponentClass = class of TComponent;
This allows for dynamic binding to virtual constructors. The TComponent constructor is virtual. The streaming framework needs to instantiate classes derived from TComponent. It does so something like this:
var
ComponentClass: TComponentClass;
Component: TComponent;
....
ComponentClass := GetComponentClassSomehowDoesntMatterHow;
Component := ComponentClass.Create(Owner);
Now, because TComponent.Create is virtual, this is bound in a polymorphic fashion. If TComponentClass is TButton, then TButton.Create is called. If TComponentClass is TPanel, then TPanel.Create is called. And so on.
The most important thing to realise is that the class that is constructed is determined only at runtime. Note that many languages lack this capability, most notably C++.

Delphi: Memory leak when creating a TStringList inside a class

I have this pieces of code
TSql = class
private
FConnString: TStringList;
public
property ConnString: TStringList read FConnString write FConnString;
constructor Create;
destructor Destroy;
end;
var
Sql: TSql;
...
implementation
{$R *.dfm}
constructor TSql.Create;
begin
//inherited Create;
FConnString:=TStringList.Create;
end;
destructor TSql.Destroy;
begin
FConnString.Free;
//inherited Destroy;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Sql.Create;
Sql.ConnString.Add('something');
showmessage(Sql.ConnString.Text);
Sql.Destroy;
end;
Why when creating the FConnString is creating a memory leak, after a press the button?
..................................
..................................
..................................
..................................
There are two things I see. The first of which was already covered by the other comments and answer regarding the lack of "override" on the destructor.
The second issue is the property declaration itself. In general, you should never declare a property that references an object field in the "write" clause. The reason is that assigning to that property will "leak" the existing instance in that field. Use a method for the "write" clause of the property declaration:
property ConnString: TStringList read FConnString write SetConnString;
...
procedure TSql.SetConnString(Value: TStringList);
begin
FConnString.Assign(Value);
end;
Also notice that this method does not overwrite the FConnString field either. It merely copies the "value" or the "content" of the Value TStringList into the FConnString instance. In this manner the TSql instance is in complete and total control over the lifetime of that field. It is the responsibility of the code assigning that property to control the lifetime of the Value TStringlist.
EDIT The actual problem
The original code in the question was as follows:
procedure TForm1.Button1Click(Sender: TObject);
begin
Sql.Create;
Sql.ConnString.Add('something');
showmessage(Sql.ConnString.Text);
Sql.Destroy;
end;
The problem line was Sql.Create; which should have been Sql := TSql.Create;. The reason this causes a memory leak is as follows:
Sql.Create; is called from a nil reference.
This calls TStringList.Create; and attempts to assigned the result to FConnString.
Because Sql is a nil reference, this triggers an Access Violation.
The problem is there is no way to destroy the TStringList instance that was created.
Additional problems in original answer
Your destructor is virtual, you're not overriding.
You're not calling your inherited Destructor.
TSql = class
private
FConnString: TStringList;
public
property ConnString: TStringList read FConnString write FConnString;
constructor Create;
destructor Destroy; override; //Correction #1
end;
destructor TSql.Destroy;
begin
FConnString.Free;
inherited Destroy; //Correction #2
end;
EDIT
A few general tips:
I applaud you for using composition (making FConnString a member instead of inheriting from TStringList). However, by exposing it publicly, you would lose many of the benefits. Specifically you would be exposed to Law of Demeter violations. I'm not saying never do it. But be aware that you can create a maintenance problem down the line if a large amount of client code accesses ConnString directly.
Declaring FConnString: TStringList; violates the principle of Program to an interface, not an implementation. TStringList is a specific implementation of TStrings and this declaration prevents use of other subclasses of TStrings. This is more of a problem combined with #1: if in a few years time you find and want to switch to a different/better subclass implementation of TStrings client code that is binding to TStringList now creates much more work and risk. Basically the preferred aproach can be summed up as:
Declare the variable as the abtract base type.
Create the instance as the specifically chosen implementation subclass.
Let polymorphism ensure subclass behaviour is applied correctly in overridden methods.
Again this is a general guideline. If you specifically need access to properties/methods that were added at the TStringList level of the hierarchy, then you have to bind to that class. But if you don't need it, don't do it.
You forgot to declare Destroy() with the override specifier, so TSql.Destroy is not actually being called when the object is destroyed.
destructor Destroy; override;
The object is not created correctly. It must be:
Sql:=TSql.Create;
From here is coming the memory leak.