Why static is needed in the one case and is not mandatory in another one? - delphi

FreePascal, Delphi mode. After some experiments I found that this code is compiled, FPC says me that class procedure must be "static". But my question is: then why operator Equal does not need "static" and it's compiling fine?! Also I can not understand what is the difference to have "class" procedure and "class" with "static" (for example, in Python in classmethod you get argument - reference to the class, in staticmethod - you have not such argument).
type TPos = record
FLine: Word;
FPos: Word;
class procedure Init(out a: TPos); static;
class operator Equal(a, b: TPos): Boolean;
end;
PS. I set "delphi" tag because: 1) it's written in delphi mode 2) because I found the same documentation for Delphi: about class and static keywords.

Contrary to what you state, a non-static class method does have a reference to the class passed as an argument. It's an implicit argument named Self.
For class methods on records as opposed to classes, since there is no inheritance, this Self parameter would serve no purpose, and so it is never passed. Hence all class methods on records must be static.
A class operator is implicitly a static method and so you don't need to state that. In other words, operator implies static.

Related

Why make a class with only 1 static function?

Recently I ran into the following code:
interface
TSomeClass=Class
public
class function SomeFunction(sMyString: string) : ISomeInterface;
end;
implementation
TSomeClass.SomeFunction(sMyString: string) : ISomeInterface;
begin
...Get some dependency.
end;
Basically a class with 1 class function in it.
What's the benefit of this construct over just having the function in a unit without it being part of a class?
like:
interface
function SomeFunction(sMyString: string) : ISomeInterface;
implementation
SomeFunction(sMyString: string) : ISomeInterface;
begin
...Get some dependency.
end;
It largely comes down to personal choice.
However, one benefit that the class function provides is a means to fake namespaces. Suppose that the function name that you wanted to use was quite short and general. In that situation it might collide with another symbol having the same name, defined in a different unit. At which point you might be subject to the vagaries of unit use order, and may need to fully qualify the name. By using a class function, you force the user to qualify the function name with its class.
Another point to make here is that the two alternatives that you present have a potentially significant difference. The class function in your question has a Self pointer. Unlike for an instance method, this refers to the class rather than an instance. To make the two functions completely equivalent you would declare the class function to be static.
class function SomeFunction(sMyString: string): ISomeInterface; static;
Of course, one thing that can be done with a non-static class function, is that it can be used where an of object method type is required.

Declare functions from C-DLL with different parameters in Pascal

I got following problem:
I'm loading a function of a C-DLL in my Lazarus project like
#dpstate_callCustomfunction:= GetProcAddress(mConnectorLibrary, 'dpstate_callCustomfunction');
this function got different implementations with different variables in the C-DLL, so I have to declare it more than 1 time in the Lazarus project. I tried it like:
var dpstate_callCustomfunction: function(plugin, method, paramName: string; customfunctionCallbackFunction: string; id: PChar): integer; stdcall; overload; override;
var dpstate_callCustomfunction: function(plugin, method, paramName: string; resultParam: PChar): integer; stdcall; reintroduce; overload;
But the compiler tells me following Errors:
"Error: Procedure directive "OVERRIDE" not allowed in procvar declaration"
"Error: Procedure directive "OVERLOAD" not allowed in procvar declaration"
What am I doing wrong? =/ If I remove the "var" it compiles, but I think I need the "var" or am I wrong?
Since you are declaring variables, they must have different names. Unlike functions, procedures and methods which can overload the same name.
So, solve your problem by choosing different names for your two variables.
And also remove everything after the stdcall in your two variable declarations. Those keywords only apply to procedures and methods, and not to procedural variables.
You have to use variables if you are going to link explicitly using GetProcAddress. You need a variable to hold the function pointer returned by GetProcAddress. If you linked implicitly using the external keyword, then you would not have a variable. And then you could declare functions overloaded with the same name.
I must admit that I am surprised that you chose the same name for these variables. They must have different names in the C code, and they must be exported from the DLL with different names. I hope you aren't trying to call the same function with different parameter lists. That certainly will not work.
The other problem that I can see you will have is that your string parameters cannot possibly match the parameters used in the C library. You'll need to use PChar I suspect. But that's really the topic for a different question.

Store Generic Array in Class using Delphi XE

Using the structure below, how can I define my TAnimalCollection class in order to store my collection? Calling either SelectAll or SelectTop10 will update the SelectedRecords.
Removing the private field allows the code to compile, but there is no mechanism to then store the returned result set.
TDog = class
private
FBreed: string;
public
property Breed: string read FBreed write FBreed;
end;
TCat = class
private
IsWild: string;
public
property IsWild: string read FIsWild write FIsWild;
end;
TMyArray<T> = array of T;
TAnimalCollection = class
private
SelectedRecords: TMyArray<T>; // Generates: Undeclared Identifier: 'T'
public
function SelectAll<T>: TMyArray<T>;
function SelectTop10<T>: TMyArray<T>;
// Other Methods
end;
First, you don't need TMyArray; the built-in TArray type does the same thing.
The compiler is correct, though. In your field declaration, there's no such thing as T. The generic argument needs to be introduced on the left of a declaration before it can be used on the right. If Delphi supported generic fields, the declaration would look like this:
SelectedRecords<T>: TArray<T>;
But it doesn't, and you wouldn't want it to in this case anyway. You apparently want to store two completely unrelated classes together in the same array simultaneously. An array is always of a single type. The only single type that unifies TDog and TCat is TObject, so your array needs to be of that type:
SelectedRecords: TArray<TObject>;
// or, more conventionally,
SelectedRecords: array of TObject;
You're welcome to declare a "generic array," but only as a field of a generic class or a variable of a generic method. If you could declare a standalone generic array, try to think of when the actual type of the array elements would be determined. If not at the point you declare the array, then when? With classes and methods, you specify the type argument(s) when you declare a variable of the class, instantiate the class, or call the method. Those are uses that are separate from their declarations, and each use is distinct. When you declare a variable, you must use it the same way you declared it — a variable's type cannot change without recompiling the program.

Assigning interface pointers in a Delphi 6 class declaration?

Despite years of Delphi programming I just ran into a class declaration style I had never seen for a class that supports IUnknown:
TBCUnknown = class(TBCBaseObject, IUnKnown)
private
FRefCount: integer;
FOwner : Pointer;
protected
function IUnknown.QueryInterface = NonDelegatingQueryInterface;
function IUnknown._AddRef = NonDelegatingAddRef;
function IUnknown._Release = NonDelegatingRelease;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
...
As you can see, assignments of class methods to IUnknown interface methods are being done right in the class declaration. This looks really strange to me especially since I don't see how the IUnknown methods could be assigned to, before the constructor is called. Is this some kind of compile-time shortcut for making assignments between a class's methods and the interface pointers for an interface the class accepts, that are later resolved at run-time? If someone could provide a little information on how this works and what Delphi idiom supports this kind of construct I'd like to know.
It's called Method Resolution Clause and it allows you to specify which method actually implements the specified interface method. This means that the implementing method can have a different name than the method declared in the interface (but the method signature still has to match). Without the clause, Delphi automatically resolves the implementation methods based on their names.
In your example, the declaration means that IUnknown._AddRef is implemented by TBCUnknown.NonDelegatingAddRef and IUnknown._Release by TBCUnknown.NonDelegatingRelease.
As far as I know, this has been supported from the beginning when interface support was added to the language. You probably haven't noticed it because it's not used or needed so often.
This is what is known as a Method Resolution Clause. To quote from the documentation:
You can override the default name-based mappings by including method resolution clauses in a class declaration. When a class implements two or more interfaces that have identically named methods, use method resolution clauses to resolve the naming conflicts.

Delphi, is possible have a property and function with the same name?

consider this code
type
TMyObject=class
private
FName: Integer;
function Name: Integer;
public
property Name : Integer read FName;
function Name(Param1 : integer) : Integer; overload;
end;
Is possible in delphi create a property and a function (or procedure) with the same name?
Exist any directive or compiler switch which allow create a class like that?
No, it is not. In addition, there is no directive or compiler switch that would allow this.
The answer is in the error message that you got when you tried this...you did try it right?
Since i see the overload keyword. I suspect that perhaps what you need default are parameters
If you use
function Name(Param1: Integer = SOME_VALUE): Integer;
it can be called as either :=Name or :=Name(5)
By accident I discovered it is possible to have a class with a property that has the same name as a function in the parent class (or vice versa).
However, I would avoid this because it will confuse you. Especially if the function and property have different meanings!
Currently, the compiler cannot do what you want.
In theory, a future version of the compiler could:
The signature of a method (overloaded or not) consists of the name and the parameter types.
The same holds for the signature of indexed properties.
Since the signature spaces of properties and methods are partially linked (hence the compiler error message), that combined space could be extended to include property overloads.
Of course that extension can backfire because of backward compatibility.
--jeroen

Resources