Dart using variable to hold set of constructor parameters, to be used in multiple constructors? - flutter

is there a way to use some variable or any holder to store constructor parameters,
to be able to pass them to multiple constructors without repeating the values?
I think its possible if the constructor has only positional parameters (no named parameters).
var parametersHolder={
named1: "str",
named2: "lorem",
};
// normal usage
constructorA(named1: "str", named2: "lorem");
constructorB(named2: "lorem",named1: "str" );
my question is how to do the following in dart:
constructorA(parametersHolder);
constructorB(parametersHolder);
so is that achievable ?
Thanks

If you really want, you could use Function.apply with a constructor tear-off:
class Foo {
String named1;
String named2;
Foo({required this.named1, required this.named2});
#override
String toString() => 'Foo: $named1 $named2';
}
void main() {
var namedArguments = {
#named1: 'str',
#named2: 'lorem',
};
var foo = Function.apply(Foo.new, null, namedArguments) as Foo;
print(foo); // Prints: Foo: str lorem
}
Note that doing this sacrifices compile-time type-safety.

You can define a class to hold your parameters like this:
class MyClass{
late final int myInt;
late final String myString;
MyClass.firstConstructor(MyClassParams params){
this.myInt = params.myInt;
this.myString = params.myString;
}
MyClass.secondConstructor(MyClassParams params){
this.myInt = params.myInt;
this.myString = params.myString;
}
}
class MyClassParams{
final int myInt;
final String myString;
const MyClassParams(this.myInt, this.myString);
}

Related

final variables can't be reassigned, but the object can be mutated in flutter

https://stackoverflow.com/a/55990137/462608
comment:
"Can't be changed after initialized" is ambiguous. final variables can't be reassigned, but the object can be mutated. –
jamesdlin
Feb 19 at 17:43
and https://stackoverflow.com/a/50431087/462608
a final variable's value cannot be changed. final modifies variables
What do both these statements mean? Please give examples.
Consider the following class:
class SampleObject {
int id;
String value;
SampleObject(this.id, this.value);
}
final variable can't be reassigned:
void main() {
final obj1 = SampleObject(1, "value1");
// the following line will gives error:
// The final variable 'obj1' can only be set once
obj1 = SampleObject(1, "value2");
}
But the object property can be changed (is mutable):
void main() {
final obj1 = SampleObject(1, "value1");
obj1.value = "value2";
print(obj1.value);
}
But it becomes an immutable object if you set all the property in the class to final:
class SampleObject {
final int id;
final String value;
SampleObject(this.id, this.value);
}
where it gives error when you're trying to reassign a value to its property:
void main() {
final obj1 = SampleObject(1, "value1");
// the following line will gives error:
// 'value' can't be used as a setter because it's final.
// Try finding a different setter, or making 'value' non-final
obj1.value = "value2";
}
Imagine the example below:
void main() {
final student = Student('Salih', 29);
print('Student before $student');
student.age = 30;
print('Student after $student');
}
class Student {
Student(this.name, this.age);
final String name;
int age;
#override
String toString() => 'Age is $age and name is $name';
}
One of the fields of the Student object is mutable. This way we can reassign it. What others mean above is that, the object reference of the final variables will be assigned first but internals of the object can be changed.
In our example, final would be preventing to re-assign something to student object but it will not prevent us to re-assign a value within the object.
You can run the code on dartpad.dev above and see the result as follows:
Student before Age is 29 and name is Salih
Student after Age is 30 and name is Salih

Is there a quick way to create a new instance of a Dart class from an existing object?

Basically wondering if there is a quick way other than creating a method to create a new class instance from itself so the example below would print 9, not 15.
void main() {
final classOne = SomeClass(mutableString: 'Hello', mutableInt: 9);
final classTwo = classOne;
classTwo.mutableInt = 15;
print(classOne.mutableInt);
}
class SomeClass {
SomeClass({required this.mutableString, required this.mutableInt});
String mutableString;
int mutableInt;
}
Thanks
You can add a method in the class which retuns the same object.
For example :
I am ading copyWith method in SomeClass
class SomeClass {
SomeClass({required this.mutableString, required this.mutableInt});
String mutableString;
int mutableInt;
SomeClass copyWith({int? mutableInt}) {
return SomeClass(
mutableString: this.mutableString,
mutableInt: mutableInt ?? this.mutableInt,
);
}
}
Now you can use the method as :
void main() {
final classOne = SomeClass(mutableString: 'Hello', mutableInt: 9);
final classTwo = classOne.copyWith(mutableInt:15);;
print(classOne.mutableInt);
}
#anoncgain solution is correct up-to an extent.
You can also do the same as
class SomeClass {
//...other code ....
String? mutableString; //make your params nullable
int? mutableInt;
//declare a named constructor to copp the existing object value.
SomeClass.copy(SomeClass object){
mutableString = object.mutableString;
mutableInt = object.mutableInt;
}
}
Then you can use it as
final classTwo = SomeClass.copy(classOne);
//it will copy the values to the newly created object
//rather then storing the reference of the object

How to cast static variable as a constant and use it to pass to class constructor that expecting final

Got an error for following code
Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
static const MyClass darkerText = MyClass(param);
Understood that using static in this instance might be inappropriate. Just wanted to look if there is any possible way to do so.
class MyClass {
final int total;
MyClass(total);
}
class Test {
static int param = 10;
static const MyClass darkerText = MyClass(param);
}
main() {
new Test();
}
You seem to have misunderstood the point of const and final. const is for values that are known at compile time, so in your case this is possible, though somewhat pointless, if all your values are compile time constants:
class MyClass {
final int total;
const MyClass(this.total);
}
class Test {
static const int param = 10;
static const MyClass darkerText = MyClass(param);
}
main() {
new Test();
}
What is more normal is to use final variables, which can be set during the program's lifecycle but don't change after being set, in which case you would use something like this:
class MyClass {
final int total;
MyClass(this.total);
}
class Test {
static int param = 10;
static final MyClass darkerText = MyClass(param);
}
main() {
new Test();
}
You can copy paste run full code in DartPad
You need to use this.total and remove const keyword of darkerText
class MyClass {
final int total;
MyClass(this.total);
}
class Test {
static int param = 10;
static MyClass darkerText = MyClass(param);
}
main() {
print(Test.darkerText.total);
}
As the error says, your MyClass is a non-const constructor.Make it const:
class MyClass {
final int total;
const MyClass(this.total);
}
class Test {
static const int param = 10;
static const MyClass darkerText = MyClass(param);
}
void main() {
new Test();
}

Dart Flutter How to initialize a class method inside of its class?

Here is my class:
class WorldTimeClass {
String flag;
String url;
String time;
String location;
WorldTimeClass({this.flag, this.url, this.time, this.location});
Future<String> getData() async {
try{
Response load = await get('http://worldtimeapi.org/api/timezone/$url');
Map x(){if(load.statusCode == 200){
print(load.statusCode);
Map map = jsonDecode(load.body);
return map;}
else{
print('No Access');
return {1:'NoAccess.'};}
}
Map myMap = x();
String datetime = myMap['utc_datetime'];
String offsetUTC = myMap['utc_offset'];
DateTime dateTimeObjectConvert = DateTime.parse(datetime);
// Below converts the datetime string to a DateTime Object and then converts the UTC Offset to a substring only '01' out of +01:00 and then converts it to an int Object and then adds it to the DateTime Object as a Duration (hours);
dateTimeObjectConvert = dateTimeObjectConvert.add(Duration(hours: int.parse(offsetUTC.substring(1,3))));
return time = dateTimeObjectConvert.toString();
}
catch(e,s){
return 'Could not access time data from API.\nWe are sorry, please try again.\nError occured: $e';
}
}
var myString = getData().then((value) => value);
DateFormat pretty = DateFormat().add_jm().format(myString);
}
How can I access myString and execute it inside my class in order to use the resulting String object to use it inside a second method pretty ?
Also, I need to understand what does the below exception mean?
Only static members can be accessed in initializers.
Only static members can be accessed in initializers.
This basically means that you cannot call methods of a class or access properties of a specific class directly under class declaration.
You are getting the error on those two lines:
var myString = getData().then((value) => value);
DateFormat pretty = DateFormat().add_jm().format(myString);
Therefore create a method that returns a String then all you have to do is to call that method and it will give you the String, and add the code above inside the method:
String getDateFormat(){
var myString = getData().then((value) => value);
return DateFormat().add_jm().format(myString);
}
To access your myString variable you'll have to do one of those things:
Instantiate an WorldTimeClass object and access it using yourWorldClassObject.myString
Make it into in static member by using the static keyword like static var myString. This is what " Only static members can be accessed in initializers. " is all about. You have to create an instance of the class if you want to access it's properties, or make them static to access them without the need to instantiate an object. Simply WorldTimeClass.myString.

How can I get a default and a parameterized constructor inside the same class in Dart/Flutter?

I know that in C++ we could have both of the constructors without a problem. In Dart when I'm trying to write two constructors, it says "The default constructor is already defined"
class Human {
double height;
int age;
Human()
{
height = 0;
age = 0;
}
Human (double startingheight){ //The default constructor is already defined
height = startingheight;
}
}
Dart doesn't support methods/functions overload and will not have it in any visible future.
What you can do here is to make the parameters optional with default value:
Either as positional arguments:
class Human {
double height = 175;
Human([this.height]);
}
var human1 = Human();
var human = Human(180);
or named:
class Human {
final double height;
Human({this.height = 175});
}
var human1 = Human();
var human = Human(height: 180);
class Human{
Human(double height, int color) {
this._height = height;
this._color = color;
}
Human.fromHuman(Human another) {
this._height = another.getHeight();
this._color = another.getColor();
}
}
new Human.fromHuman(man);
This constructor can be simplified
Human(double height, int age) {
this._height = height;
this._age = age;
}
to
Human(this._height, this._age);
Named constructors can also be private by starting the name with _
Constructors with final fields initializer list are necessary:
class Human{
final double height;
final int age;
Human(this.height, this.age);
Human.fromHuman(Human another) :
height= another.height,
age= another.age;
}
Try these
//Using Default parameter values
Human({this.height = 0.0, this.age = 0});
// Named constructor
Human.startingHeight(double startingHeight){
height = startingHeight;
age = 0;//or don't use this if you want it null
}
For more info check out this page: https://dart.dev/guides/language/language-tour