Parameter issue on Dart - dart

can somebody explain why
class SaveGlove {
final String serialNumber;
final String productionDate;
SaveGlove(this.serialNumber, this.productionDate);
SaveGlove.fromJson(Map<String, Object?> json)
: this(
serialNumber: json['serialNumber']! as String,
productionDate: json['prductionDate']! as String,
);
Map<String, Object?> toJson() {
return {
'serialNumber': serialNumber,
'prductionDate': productionDate,
};
}
}
doesn't work but when I change parameter in constructor like that:
SaveGlove({required this.serialNumber, required this.productionDate});
it works?

Your original code doesn't work because your constructor is declared to take two positional arguments,
SaveGlove(this.serialNumber, this.productionDate);
but you are calling it with named arguments:
: this(
serialNumber: json['serialNumber']! as String,
productionDate: json['prductionDate']! as String,
);
(This is a redirecting generative constructor, which tries to redirect to the SaveGlove constructor by passing it two named arguments.)
That doesn't work, positional parameters need positional arguments.
If you had written the redirecting constructor as:
: this(
json['serialNumber']! as String,
json['prductionDate']! as String,
);
then it would have worked.
Changing the constructor to take two named parameters also makes the redirection be valid.

It is because Null Safety is added in Dart. In simple words, Null Safety means a variable cannot contain a ‘null’ value unless you initialized with null to that variable. All the runtime null-dereference errors will now be shown in compile time with null safety.
So as you are initializing variables serialNumber & productionDate you have two options:
Either make it compulsory to provide those variables values from constructor by adding required keyword.
class SaveGlove{
String serialNumber;
final String productionDate;
SaveGlove({required this.serialNumber, required this.productionDate});
}
Or declare those variables as nullable, i.e which can accept null values. So you don't need the required keyword:
class SaveGlove{
String? serialNumber;
String? productionDate;
SaveGlove({this.serialNumber,this.productionDate});
}

Related

Dart Annotation - Unable to pass non constant method

How can I pass-in non-constant method in Dart Annotations?
Here is my annotation:
class Injectable {
final String name;
final Scope scope;
final List<Provider>? provider;
const Injectable({this.name = '', this.scope = Scope.factory, this.provider});
}
class Provider<T> {
final Type? useClass;
final Object? useValue;
final T? Function()? usefactory;
final List<Type> deps;
const Provider(
{this.useClass, this.useValue, this.usefactory, this.deps = const []});
}
This works fine:
But when I try to directly pass-in the function. I am getting a compile error:
Any idea what is happening?
Error: Arguments of a constant creation must be constant expressions. (Documentation) Try making the argument a valid constant, or use 'new' to call the constructor.
Invalid constant value.
The argument type 'ServiceA' can't be assigned to the parameter type 'ServiceA? Function()?'. (Documentation)
Please try to remove the brackets from inject<ServiceA>(). Just make it inject<ServiceA>.
usefactory-s type is a function, but in your case, you are passing ServiceA type data.

class parameter or class identifier query

I am new in Dart and works on an app that has a class look like this:
abstract class BaseUseCase <In,Out> {}
My question is then, what is In and Out?
In and Out are type arguments. They are used to allow the code in the class to use objects of an unknown type while remaining consistent and type-safe.
For example, say you wanted to have a method in a class that would take a list of any type, perform a string conversion operation on every element, and then return a strongly typed map of results:
class Stringifier<T> {
Map<T, String> stringify(List<T> input) =>
{for (final entry in input) entry: input.toString()};
}
void main() {
Stringifier<int>().stringify([1, 2, 3]);
// Result: <int, String>{1: '1', 2: '2', 3: '3'}
}
Note that the return type and input argument type use the generic T type. This ensures that only a list of the given type can be passed in, and that the resultant map will have the correct key type.
Type arguments can be used in other declarations as well, such as function declarations - indeed, the example above can be simplified, and declared outside a class:
Map<T, String> stringify(List<T> input) { /* ... */ }
More information on generics can be found in the Dart Language Tour, as well as in the "Generics" section of the Dart 2 language specification.

Optional Arguments in dart class constructor

why there is error while am trying to construct my constructor i want to have a named paramters but not required ones how i can fix this
class Task {
int id;
String title;
String description;
**Task({this.id , this.title , this.description}); // Giving me Errors here**
Map<String , dynamic> toMap()
{
return {
'id' : id,
'title' : title,
'description' : description,
};
}
#override
String toString() {
return 'Task{id: $id, name: $title, age: $description}';
}
}
If you don't want the arguments to be required, you have to allow them to be null by adding a question mark to their type, so Dart will know that they don't need to be initialized. Like this:
int? id;
String? title;
String? description;
Another solution is to give them a default value in the constructor, but be careful to assign them values that won't conflict with the rest of your code:
Task({this.id=-1, this.title='Title' , this.description = 'Description'});
Choose the approach that suits you best: you can also use a mix of the two solutions, like making some properties nullable and giving a default value to the others.

How can I make sure that a non-nullable type will always be inferred?

I'm currently making an API that I want the optional value of type T to never be nullable (having null-safety enabled, of course).
Let's exemplify with the following:
void main() {
T nonNullableGeneric<T>(T value) {
if(value == null) {
throw 'This is null';
}
return value;
}
nonNullableGeneric(1); // Works fine
nonNullableGeneric(null); // Works fine BUT I would like that the type inference would not allow a nullable value
// Now this works as expected:
// "the argument type 'Null' can't be assigned to the parameter type 'int'."
//
// ... but I have to specify the type `T`, which is not clear given my function signature, that clearly
// requires a non-nullable value of type `T`
nonNullableGeneric<int>(null);
// How can I make the following call:
// nonNullableGeneric(null)
// to throw me something like "the argument type 'Null' can't be assigned to a parameter type 'T'."?
}
I've also created a dartpad.
As you can see, I must always specify the type if I want to make sure that it can't be Null when using a generic argument.
How can I make sure that it will never allow a nullable type?
I've found that the answer was really obvious, although I think it's reasonable to mention anyways: just make your type T constraints (extend) to a type of Object. This will make sure that that particular argument can never be optional.
Quoting the Object docs:
/// ...
/// Because `Object` is a root of the non-nullable Dart class hierarchy,
/// every other non-`Null` Dart class is a subclass of `Object`.
/// ...
So, in this example that I've mentioned, the solution would be:
void main() {
T nonNullableGeneric<T extends Object>(T value) {
return value;
}
nonNullableGeneric(1); // Works fine
// Throws a:
// Couldn't infer type parameter 'T'. Tried to infer 'Null' for 'T' which doesn't work: Type parameter 'T' declared to extend 'Object'.
// The type 'Null' was inferred from: Parameter 'value' declared as 'T' but argument is 'Null'.
// Consider passing explicit type argument(s) to the generic
nonNullableGeneric(null);
}

Difference between class constructor syntax in Dart

I have a class that I am creating that looks like this:
class Movie {
final String title, posterPath, overview;
Movie(this.title, this.posterPath, this.overview);
Movie.fromJson(Map json) {
title = json["title"];
posterPath = json["poster_path"];
overview = json['overview';
}
}
I am getting a warning that says that "The final variables 'overview', 'posterPath', & '1' more must be initialized. There are also warnings around each variable saying 'title' can't be used as a setter because it is final.
When I write the constructor using this syntax, the warnings go away:
Movie.fromJson(Map json)
: title = json["title"],
posterPath = json["poster_path"],
overview = json['overview'];
What exactly is going on here?
Dart objects must be fully initialized before anyone gets a reference to the new object. Since the body of a constructor can access this, the object needs to be initialized before entering the constructor body.
To do that, generative Dart constructors have an initializer list, looking similiar to C++, where you can initialize fields, including final fields, but you cannot access the object itself yet. The syntax:
Movie.fromJson(Map json)
: title = json["title"],
posterPath = json["poster_path"],
overview = json['overview'];
uses an initializer list (the list of assignments after the :) to initialize the final instance variables title, posterPath and overview.
The first constructor uses an "initializing formal" this.title to directly put the parameter into the field.
The constructor
Movie(this.title, this.posterPath, this.overview);
is effectively a shorthand for:
Movie(String title, String posterPath, String overview)
: this.title = title, this.posterPath = posterPath, this.overview = overview;
Your constructor can combine all of these and a body:
Movie(this.title, this.posterPath, String overview)
: this.overview = overview ?? "Default Overview!" {
if (title == null) throw ArgumentError.notNull("title");
}
(A const constructor cannot have a body, but it can have an initializer list with some restrictions on the allowed expressions to ensure that they can be evaluated at compile-time).
Dart separates properties initialization from the constructor body.
A constructor has 3 parts :
the name/parameters definition
properties initialization/super call/asserts
A body, similar to a function immediately run on construction
Both the initialization and body parts are optional.
final variables must be initialized on the first 2 parts. They cannot be initialized inside the body.
A full constructor will look like the following :
MyClass(int value)
: assert(value > 0),
property = value,
super();
{
print("Hello World");
}
The main purpose of this initializer part is for body-less constructors which allows const constructors, a dart specific feature. See How does the const constructor actually work? for more details on these.
I just found some documentation around this, & it seams that the second version with the : is what's called the "initializer list" which allows you to initialize instance variables before the constructor body runs.
There is more detail around this in the documentation here.

Resources