I got error massage Default value required for 'DefaultPort' when i create the following constructor
type
MyIdServer = class
public
constructor Create(const AOwner: TComponent = nil; const DefaultPort: Word; SilentExceptions: Boolean);
destructor Destroy; override;
end;
How i can solve it without changing the order of the parameters ( such the following works fine).
constructor Create(const DefaultPort: Word; SilentExceptions: Boolean; const AOwner: TComponent = nil);
Parameters with default values must go last in the argument list. If any parameter has a default value, all subsequent parameters must also have default values.
The only other option is to define two overloads:
constructor Create(const AOwner: TComponent;
const DefaultPort: Word;
SilentExceptions: Boolean); overload;
constructor Create(const DefaultPort: Word;
SilentExceptions: Boolean); overload;
and have the second one call the first one with a nil argument for the AOwner.
The underlying problem is that parameters with default values must be declared after any non-default parameters, where you have attempted to make the first parameter default, followed by non-default parameters.
However, the involvement of an aOwner TComponent parameter strongly suggests that your example code is not entirely complete as this implies that your server class will be implemented as a sub-class of some TComponent derived super-class.
If that is the case then I believe there is an additional consideration.
As a sub-class of a TComponent your class will inherit a virtual constructor accepting a single, Owner parameter.
First of all, this will cause a warning telling you that your constructor is hiding the inherited one. You could add a reintroduce directive to your constructor to address the warning:
constructor Create(const AOwner: TComponent; const DefaultPort: Word; SilentExceptions: Boolean); reintroduce;
However, this entirely replaces the inherited, virtual constructor with your new one, which is probably not what you really intend. You could also add the overload directive to retain access to both your new constructor and the inherited one:
constructor Create(const AOwner: TComponent; const DefaultPort: Word; SilentExceptions: Boolean); reintroduce; overload;
This addresses the simple fact of the compiler complaints and ensures that the virtual constructor is retained on the derived class.
But it raises a question: What values should an instance of your class adopt for the parameters supplied in your constructor if (or when) the inherited constructor is used that does not allow these values to be specified ?
This will still be possible if a class reference is used to instantiate your class. e.g.
var
serverClass: TComponentClass;
server: MyIdServer;
begin
serverClass := MyIdServer;
// .. elsewhere ...
server := serverClass.Create(frmMain);
end;
Most likely this sort of instantiation of your class will only occur if your component is streamed from a form resource so as long as the values set by those additional parameters are also published properties with values also set by the streaming mechanism then there may not be any problem.
But it does prompt a further question of whether a new constructor is actually what is required or desired ?
Rather than overload the constructor, it might be more appropriate instead to provide a factory method on the class:
MyIdServer = class(TComponent)
public
class function NewServerWithDefaults(DefaultPort: Word; SilentExceptions: Boolean): MyIdServer;
end;
The implementation of this factory method will call the appropriate constructor with a NIL owner parameter and then initialise the desired properties as specified in the passed parameters:
class function MyIdServer.NewServerWithDefaults(DefaultPort: Word; SilentExceptions: Boolean): MyIdServer;
begin
result := MyIdServer.Create(NIL);
// Assuming the properties involved here but you get the idea...
result.DefaultPort := DefaultPort;
result.SilentExceptions := SilentExceptions;
end;
You could argue that this is "Angels Dancing on a Pin Head" since the end result is the same, in terms of the behaviour of the code. The difference lies in the resulting class design itself.
Whether this is more appropriate or desirable than simply introducing a new constructor is ultimately up to you. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With