I'd like to subclass the XMLUnit.NET CompareConstraint class in my F# code.
However, that class only has a single private constructor. If I try to inherit it, I get this compile error:
This 'inherit' declaration specifies the inherited type but no arguments. Consider supplying arguments, e.g. 'inherit BaseType(args)'.
Is there any way to inherit a class without a public constructor in F#?
This is not an F# limitation – it is not possible to inherit from a type with only private constructors in any .NET language.
Related
I've been investigating JSON parsing for my Flutter app and have a question about factory constructors that I can't resolve. I'm trying to understand the advantage of using a factory constructor versus a plain constructor. For example, I see quite a few JSON parsing examples that create a model class with a JSON constructor like this:
class Student{
String studentId;
String studentName;
int studentScores;
Student({
this.studentId,
this.studentName,
this.studentScores
});
factory Student.fromJson(Map<String, dynamic> parsedJson){
return Student(
studentId: parsedJson['id'],
studentName : parsedJson['name'],
studentScores : parsedJson ['score']
);
}
}
I've also seen an equal number of examples that DON'T declare the constructor as a factory. Both types of classname.fromJSON constructors create an object from the JSON data so is there an advantage to declaring the constructor as a factory or is using a factory here superfluous?
A normal constructor always returns a new instance of the current class (except when the constructor throws an exception).
A factory constructor is quite similar to a static method with the differences that it
can only return an instance of the current class or one of its subclasses
can be invoked with new but that is now less relevant since new became optional.
has no initializer list (no : super())
So a factory constructor can be used
to create instances of subclasses (for example depending on the passed parameter
to return a cached instance instead of a new one
to prepare calculated values to forward them as parameters to a normal constructor so that final fields can be initialized with them. This is often used to work around limitations of what can be done in an initializer list of a normal constructor (like error handling).
In your example this code
studentId: parsedJson['id'],
studentName : parsedJson['name'],
studentScores : parsedJson ['score']
could be moved to the body of a normal constructor because no final fields need to be initialized.
In the particular example in the question, there's no advantage to using a factory constructor. It makes no difference to callers (there is no expectation to receive an already-existing object), and this particular factory constructor could have been a normal constructor that delegated to the main constructor instead.
In general, the factory keyword is not very useful and provides an advantage only in special circumstances.
A factory constructor vs. a normal constructor
A factory constructor invokes another constructor.
Since a factory constructor does not directly create a new instance, it cannot use a constructor initializer list.
A normal constructor always returns a new instance of the class. A factory constructor is permitted to return an existing instance, an instance of a derived class, or null. (However, some people dislike returning null from a factory constructor. Note that returning null from a factory constructor is disallowed with null-safety.)
Due to the above, an extending class cannot invoke a factory constructor as the superclass constructor. A class that provides only factory constructors therefore cannot be extended with derived classes.
A factory constructor vs. a static method
A factory constructor can be the unnamed, default constructor of a class.
A factory constructor can be used with new. (But using new is now discouraged.)
Until Dart 2.15, constructors could not be used as tear-offs (i.e., they could not be used as callbacks), whereas static methods could.
Static methods can be async. (A factory constructor must return a type of its class, so it cannot return a Future.)
Factory constructors can be declared const.
In null-safe Dart, a factory constructor cannot return a nullable type.
In generated dartdoc documentation, a factory constructor obviously will be listed in the "Constructors" section (which is prominently at the top) whereas a static method will be in the "Static Methods" section (which currently is buried at the bottom).
After I've been noticing and wondering the same, and given I don't think the other answers actually answer the question ("I've been investigating JSON parsing [...] I'm trying to understand the advantage of using a factory constructor verses a plain constructor"), here my try:
there's no advantage or difference that I could see or understand, when parsing json, in using a factory constructor instead of a plain constructor. I tried both, and both works fine, with all the types of parameters. I decided eventually to adopt the factory constructor, because of the convenience of how the code is written, and readability, but it's a matter of choice and both will work fine in all the cases.
One of the uses of factory constructor is, we can decide which instance to create, at run-time and move all the logic to the parent's factory constructor
let's say you have 1 parent class and 2 subclasses
class GolderRetriever extends Dog{
GolderRetriever(String name):super(name);
}
class Labrador extends Dog{
Labrador(String name):super(name);
}
Then we have the parent class
class Dog{
final String name;
Dog(this.name);
factory Dog.createInstance({required String name,DogType type=DogType.UNKNOWN}){
if(type==DogType.GOLDEN_RETRIEVER){
return GolderRetriever(name);
}
else if(type==DogType.DALMATION){
return Labrador(name);
}else{
return Dog(name);
}
}
}
and also I have enum DogType
enum DogType{
GOLDEN_RETRIEVER,DALMATION,UNKNOWN
}
Then in the main Method, you just delegate which subclass instance you want to create to the parent Dog class
main() {
Dog myDog = Dog.createInstance(name:"Rocky",type:DogType.DALMATION);
Dog myNeighboursDog = Dog.createInstance(name:"Tommy",type:DogType.GOLDEN_RETRIEVER);
Dog strayDog = Dog.createInstance(name:"jimmy");
}
you can't do this with a named constructor as you can create only the instance of that class(Dog class), not its subtypes.
Now the responsibility of which instance to create is delegated to the parent class. This can remove a lot of if-else boilerplate code. When you want to change the logic, you just change that in Animal class alone.
What happens to a procedure when it is declared with the keyword dynamic?
And what is the effect of declaring it with the keyword static?
This question can be answered by reading the documentation.
The dynamic keyword introduces a method that can be overridden polymorphically. Semantically it is interchangeable with virtual, but the is implemented in a different manner. Read about it here: http://docwiki.embarcadero.com/RADStudio/en/Methods#Virtual_and_Dynamic_Methods
To make a method virtual or dynamic, include the virtual or dynamic
directive in its declaration. Virtual and dynamic methods, unlike
static methods, can be overridden in descendent classes. When an
overridden method is called, the actual (run-time) type of the class
or object used in the method call--not the declared type of the
variable--determines which implementation to activate.
To override a method, redeclare it with the override directive. An
override declaration must match the ancestor declaration in the order
and type of its parameters and in its result type (if any).
...
In Delphi for Win32, virtual and dynamic methods are semantically
equivalent. However, they differ in the implementation of method-call
dispatching at run time: virtual methods optimize for speed, while
dynamic methods optimize for code size.
In general, virtual methods are the most efficient way to implement
polymorphic behavior. Dynamic methods are useful when a base class
declares many overridable methods that are inherited by many
descendent classes in an application, but only occasionally
overridden.
Class static methods are like class methods in that they are invoked on the class rather than an instance. The difference between class static and class methods is that class methods are passed a Self pointer that contains the class, and class static methods are not. This means that class methods can be polymorphic and class static methods cannot. Read about it here: http://docwiki.embarcadero.com/RADStudio/en/Methods#Class_Static_Methods
Like class methods, class static methods can be accessed without an object reference. Unlike ordinary class methods, class static methods have no Self parameter at all. They also cannot access any instance members. (They still have access to class fields, class properties, and class methods.) Also unlike class methods, class static methods cannot be declared virtual.
With all due respect, I refer you to this question: How can I search for Delphi documentation?
So I have seen code as such:
class Whatever {
final String name;
const Whatever(this.name);
}
What does change by the fact that the constructor is marked with const? Does it have any effect at all?
I have read this:
Use const for variables that you want to be compile-time constants. If
the const variable is at the class level, mark it static const.
(Instance variables can’t be const.)
but it does not seem to make sense for the class constructor.
The constructor can't have a constructor body.
All members have to be final and must be initialized at declaration or by the constructor arguments or initializer list.
You can use an instance of this class where only constants are allowed (annotation, default values for optional arguments, ...)
You can create constant fields like static const someName = const Whatever();
If the class doesn't have a const constructor it can't be used to initialize constant fields. I think it makes sense to specify this at the constructor. You can still create instances at runtime with new Whatever() or add a factory constructor.
See also
Dartlang const constructor - how is it different to "regular" constructor
Dart factory constructor - how is it different to “const” constructor
How to make a factory constructor that returns as const value
Why does Dart have compile time constants?
How to write abstract class constructors so that it will be flexible for extending in sub classes
The "old style" (still valid) enum is a good example how to use const
https://stackoverflow.com/a/15854550/217408
Is it possible to do implicit constructor injection in F# using Ninject? If so, how?
I tried to put the [<Inject>] attribute on the type definition, but I got back an error that it's invalid.
Here is what I tried:
[<Inject>]
type Blah(x : ISword) =
The Inject attribute is for Property setter injection only. Constructor injection is implicit. Just create your bindings and then make a kernel.Get<Blah>() and Blah is created using constructor injection.
The spec allows this as follows:
class-type-defn :=
type-name primary-constr-args_opt object-val_opt '=' class class-type-body end
where
primary-constr-args :=
attributes_opt accessopt (simple-pat, ... , simple-pat)
As a result, you just need to change your code to
type Blah [<Inject>](x : ISword) =
Here's Constructor Injection in F#:
type Foo(bar : IBar) =
// class members etc. here
Any library that requires you to slap an attribute on the type in order to understand that, is doing something wrong; pick another library.
If I write
type
MyClass = class of TMyClass;
...
Obj := MyClass.Create;
the correct constructor (the one in TMyClass) is called.
If I write
var
ClassVar : TClass;
...
ClassVar := TMyClass;
Obj := ClassVar.Create;
only the TObject constructor is called.
Why? What's the difference between the two versions? Can I force the TMyClass constructor call in the second scenario?
TClass is declared as "Class of TObject" in system.pas. What constructor gets called is decided at compile-time, and all the compiler knows is what base class you're using. It doesn't know what the value of the variable will be when it runs, so it has to default to the base class. If you're using a TClass, then your base class is TObject.
If you're using a class variable, I assume you have some sort of heirarchy and you're trying to implement a factory. If you want to make sure the right constructor gets called based on the value of a class variable at runtime, not something contained in your code at compile time, you need a virtual constructor.
type
TMyBaseObject = class(TObject)
public
constructor Create; virtual;
end;
TMyClass = class of TMyBaseObject;
Use a TMyClass instead of a TClass as your class variable, and now the compiler will generate a call to TMyBaseObject.Create, which is virtual. Make sure all your derived classes override the base constructor, and you'll end up calling the right one at runtime.
TObject.Create is not virtual, you need to declare ClassVar as a classtype of a class with a virtual constructor.
I would suggest you look into overriding the AfterConstruction method that's introduced by the TObject to make polymorphism like this work.
Each class definition can introduce a new constructor, with it's own set of parameters. A class variable only knows of the constructor if the base class it's a variable for. This is all possible because a constructor is neither virtual nor overridden. You could flag the constructor virtual on your base-class, and flag all descending classes override, which blocks the parameter list. (I think if you forget 'override' the compiler warns your new constructir hides the virtual one.)
Or descend it from TComponent, which already have a virtual constructor.