Leaderboard
Popular Content
Showing content with the highest reputation on 11/26/22 in Posts
-
Not true. FValue, in your example, is available as soon as the instance has been allocated. Realistically the earliest you get to use it is inside the constructor.
-
Getters and Setters are methods called when you get (read) or set (write) property. In Delphi you don't need to have getter and setter methods. Properties can be directly connected to a field. You use getters or setters when you want to run additional code besides directly reading or writing some field value. Following is basic property declaration without any getters or setters. When you access property, compiler just directly reads or writes from associated field. TFoo = class protected FValue: Integer; published property Value: Integer read FValue write FValue; end; Following is property declaration with setter method (you can have any combination you need and you don't need to declare both methods if you just need one of them) TFoo = class protected FValue: Integer; procedure SetValue(AValue: Integer); published property Value: Integer read FValue write SetValue; end; Because getters and setters are methods, they will be a bit slower than directly using a field. If your setter is just setting a field and does nothing more, then you don't really need it. Same goes for getter. If it just returns the field then it is not needed. procedure TFoo.SetValue(AValue: Integer); begin FValue := AValue; end; If for instance you don't want to allow setting Value to zero, you might have following code in a setter. procedure TFoo.SetValue(AValue: Integer); begin if AValue <> 0 then FValue := AValue; end; You can even raise an exception if you set property to invalid value or similar. The only time when you would need to use getters and setters that just read or write to a field, is when your property needs to be accessible through interface. Interfaces require that getters and setters are methods.
-
Undeclared identifier but the code compiles
stijnsanders replied to Valter's topic in Delphi IDE and APIs
What is the exact variable type of ExcelApplication and ExcelWorkbook? I would guess Variant or OleVariant, and in that case, a technique called "late binding" is used. It both explains why you don't have code-completion, and that the code compiles even without the compiler knowing about the specific available properties and methods. Behind the scenes, the operations you do (Cells, Select and Save in this case) are resolved at runtime on the 'living' objects using hidden 'IDispatch' interfaces that list the available properties and methods by name. It was invented by Microsoft to make dynamic scripting languages work (like VBScript, and actually also something called "JScript" because they weren't allowed to call it JavaScript, but that's another story). And Delphi has excellent support for this (but a downside is it works so good you don't see anything of it and can't access it, need to get the sequence of calls exactly right and need to debug on live objects.) -
No, it doesn't. I wish it did 🙂
-
Yes. I wrote it, so I would know. Also see line 58 of the code
-
My "Execute" on Thread is not called anymore... I'm staying crazy and dont see the my error
Remy Lebeau replied to programmerdelphi2k's topic in Algorithms, Data Structures and Class Design
That should be using X.WaitFor() instead of WaitForSingleObject() directly. var x: TMyThread; begin x := TMyThread.Create(False); try // x.Start; // if suspended... X.WaitFor; finally x.Free; end; end; -
My "Execute" on Thread is not called anymore... I'm staying crazy and dont see the my error
Davide Angeli replied to programmerdelphi2k's topic in Algorithms, Data Structures and Class Design
You can't destroy the thread object until it's finished... It doesn't even have time to start. Maybe you have to do something like this: var x: TMyThread; begin x := TMyThread.Create(False); try // x.Start; // if suspended... WaitForSingleObject(X.Handle, INFINITE); finally x.Free; end; end; -
True. But if I need multiple constructors with different arguments to set up a class before use - is that class overly complicated and should it be broken down into a hierarchy?
-
Memory management has nothing to do with number of parameters in constructors. There are other reasons why having too many parameters is considered "bad", but those are all in line that having too many parameters can be indication that your class is doing too much - violates Single Responsibility Principle. In real life, having classes and functions that require a lot of parameters and that are not in violation of SRP, nor can be adequately split, are quite common, and often workarounds for solving such "issues" are more convoluted than having few parameters over the top. If there is really a need to have class fully initialized during construction and too many parameters poses an issue that cannot be meaningfully solved by splitting the class, then Builder pattern can be suitable solution. There is usually a lot of repetitive code involved in writing a Builder class, so it is useful only if you need to construct particular class in plenty of places across your application. The main problem with many parameters, especially when they are of same type, is that you can easily pass the wrong data to wrong parameter. This could be solved on IDE level, by showing names of the parameters as hints within code - not visible outside the IDE,, so calling the constructor or function would look like TPerson.Create(AFirstName: 'John', ALastName: 'Doe'); Another similar feature on language level are named parameters, where you can or must explicitly write parameter name in the code, similar to the above.
-
@David Heffernan - I rarely make classes that have so few fields that they are passed in the constructor. Most of my instance data are retrieved from database tables, and each class knows what fields to retrieve (or store). The generic container instantiates the class, the instances fill themselves from the db query. I also have polymorphic classes where each element requires different initializations, which firstly are done by default initializations in the class create, and then secondarily from attributes before the declaration of the class instance reference field. I use this mechanism to build grids in code - and not in design mode. Again, the inits and attributes are the defaults. Overrides are then applied from stored settings.
-
I would not bother with the constructor just add a method for setup and show: procedure TTracksAddEditForm.ShowForm(const AsMode: string; AiAlbum: integer; const AsTrack: string); begin FsMode := AsMode; FiAlbum := AiAlbum; // or set the controls directly FsTrack := AsTrack; Show; end; use it: TTracksAddEditForm.Create(Self).ShowForm('Insert', blah, buh); or for showmodal function TSomeValueReturningForm.ShowForm(var AVar: string): TModalResult; begin FVar := AVar; Result := ShowModal; AVar := FVar; end; use it: lStringVar := 'Initialvalue'; case TSomeValueReturningForm.Create(Self).ShowForm(lStringVar) of mrOk: DoSomething(lStringVar); else Whatever... end; the variable var TracksAddEditForm : TTracksAddEditForm; is only needed if the forms are created with Application.CreateForm() by the dpr itself. Otherwise it should be deleted immediately.
-
Apart from data validation as suggested above, you can use setters and getters for other purposes e.g procedure SetName(NewName: string); begin if NewName<>fName then begin fName := NewName; ProjectNotSaved := true; end; end;
-
I meant this: https://github.com/CPsoftBE/BackupOfCromis/tree/Limagito-patches
-
FYI CPsoftBE uploaded a fix in branch 'Limagito Patches' . Problem is solved!