"'Class.field=' isn't a valid override" when overriding a field with a more specific type - flutter

abstract class Ainterface {
String? name;
List<Binterface?>? list;
}
abstract class Binterface {
String? age;
int? len;
}
class ObjA extends Ainterface {
String? name;
List<ObjB?>? list;
ObjA({this.name, this.list});
}
class ObjB extends Binterface {
String? age;
int? len;
ObjB({this.age, this.len});
}
I used objb as the type of each item in the list, but the editor gave an error 'obja. List =' ('void function (list < objb? >?)) isn't a valid override of 'Ainterface.list=' ('void Function(List<Binterface?>?)').
How I can solve this problem?

Fields (data members) in Dart implicitly provide getters and setters as part of the interface. Therefore when you write:
abstract class Ainterface {
List<Binterface?>? list;
}
The interface is implicitly:
abstract class Ainterface {
List<Binterface?>? get list;
set list(List<Binterface?>? value);
}
The problem is that your derived class wants to provide an interface:
class ObjA extends Ainterface {
List<ObjB?>? get list;
set list(List<ObjB?>? value);
}
Even though List<ObjB?>? is substitutable for List<Binterface?>?, the reverse is not true: List<Binterface?>? is not substitutable for List<ObjB?>?, and that's the direction that matters for the setter.
The list setter in ObjA is not a safe override of the corresponding setter from Ainterface because it would allow callers to violate its contract. Ainterface.list advertises that it allows being set to any instance of a Binterface, but ObjA.list expects only an instance of ObjB. As a concrete example, if the override were allowed, then the following code would compile without error:
class AnotherB extends Binterface {}
void main() {
Ainterface a = ObjA();
a.list = [AnotherB()]; // This error would not be caught at compile-time.
}
And now a.list contains a List<AnotherB> even though ObjA.list expects List<ObjB>, and you'd eventually get an error at runtime if you try to use a.list as a List<ObjB>.
If you can logically guarantee that the above scenario will never happen, then you can use the covariant keyword to relax static type-checking and allow the override:
abstract class Ainterface {
covariant List<Binterface?>? list;
}
but I re-emphasize that the above code removes some type-safety. By using the covariant keyword, you take responsibility for ensuring that you do not violate the contract in practice.
Alternatively:
Reconsider if your abstract base class needs to expose setters as part of its interface, and expose only getters if possible.
Make Ainterface a generic class parameterized on the concrete type of Binterface:
abstract class Ainterface<DerivedB extends Binterface> {
List<DerivedB?>? list;
}
class ObjA extends Ainterface<ObjB> {
List<ObjB?>? list;
}
I'll also point out that overriding fields is usually a bad idea, and you usually should be explicitly overriding getters and setters anyway.

In the Ainterface abstract class you declared that a list should be declared of type Binterface so any class extending that class should do that. so when you want to declare a class extending this class you should consider that. if you want to also declare a list from type ObjB you can do it after that. it will be like this:
class ObjA extends Ainterface {
String? name;
List<Binterface?>? list;
List<ObjB ?>? list2;
ObjA({this.name, this.list, this.list2});
}

Related

generics not able to use functions of superclass in dart/flutter

I have a problem with the syntax in Dart. I want to be able to use a constructor on a generic class. So I let the generic class extend an abstract class which has the specified constructor. But the Code still shows me that it's not working. Does anyone have an idea?
T fetchItem<T extends JsonModel>(){
return T.fromJson();
// This line shows the error
// The method 'fromJson' isn't defined for the type 'Type'.
}
abstract class JsonModel {
JsonModel.fromJson();
}
The following solution works, but I think it's extremly ugly:
T fetchItem<T extends JsonModel<T>>(T t){
return t.fromJson();
}
abstract class JsonModel<T> {
T fromJson();
}
Constructors are not inherited. Just because a base class has a certain constructor, does not mean the derived class has that constructor.
It doesn't have anything to do with generics. If you extended a class X from your JsonModel, it simply would not have a constructor of that name.

Generic Programming: How can I access a class "fromMap" factory constructor from a Generic class

How to access a class "fromMap" factory constructor from a Generic class.
For example, Here is a very simplified class and method:
abstract class DBbase<T> {
dynamic convert(dynamic input) {
T u = T.fromMap(input.toMap());
return u;
}
}
class DB<UserModel> extends DBbase {}
The **"T.fromMap" ** doesn't work a although the "UserModel" does have the method within.
If I change that line to:
UserModel u2 = UserModel.fromMap(input.toMap());
then it works, but this defeats the purpose of defining the type as a generic.

Dart - Get current type of the class

I would like to create a class and refer to the "type of the current class".
So for example in this small snippet, I create a class A which has .child.
As it is written, the type of .child (A?) is "hardcoded", what I mean is, if I create B that extends A, .child will be of type A?. I would like it to automatically be B? "because the current class is B".
class A {
A? child;
}
class B extends A {
}
B? f(B b) {
return b.child;
}
As it is right now, it shows the error
line 10 • A value of type 'A?' can't be returned from the function 'f' because it has a return type of 'B?'.
Is there a way to do what I am trying to do? If yes, how?
One approach would be to use generics and borrow the curiously-recurring template pattern from C++ so that the base class knows the derived class's type:
class A<Derived extends A<Derived>> {
Derived? child;
}
class B extends A<B> {
}
Alternatively you could make A an abstract class and have B override child:
abstract class A {
A? get child;
}
class B extends A {
#override
B? child;
}
If A needs a setter for child, you can use covariant to appease static analysis and allow the setter's value to be checked at runtime:
abstract class A {
A? get child;
set child(A? value);
}
class B extends A {
#override
covariant B? child;
}

The instance member 'a' can't be accessed in an initializer [duplicate]

In Dart, is there a difference in assigning values right away vs in constructor like in Java?
class Example {
int x = 3;
}
vs
class Example {
int x;
Example() {
x = 3;
}
}
I ask because when I was using Flutter and tried to assign a Function that uses setState to a variable, it was not possible with the former method but possible with the latter.
In your trivial case, it doesn't matter.
In general, you can initialize instance variables in a few ways:
Inline (field initializers)
class Example1 {
T x = value;
}
Advantages:
Direct, concise.
Member will be initialized in all constructors.
Can be used to initialize final or non-nullable members.
Member is initialized before invoking base class constructors, which is important when the base class constructor calls member functions that are overridden by the derived class.
Disadvantages:
Cannot depend on construction arguments.
Usually cannot depend on this since the initialization occurs before this becomes valid (i.e., cannot depend on other instance members). (An exception is if the member is initialized lazily by declaring it late. This requires the null-safety feature to be enabled.)
Initializer list
class Example2 {
T x;
Example2() : x = value;
}
Advantages:
Can be used to initialize final or non-nullable members.
Member is initialized before invoking base class constructors, which is important when the base class constructor calls member functions that are overridden by the derived class.
Can utilize construction arguments.
The initialized variable always refers to a member variable, never to a constructor parameter.
Disadvantages:
If the class has multiple constructors, initialization would need to be duplicated, or constructors should redirect to a common constructor.
Cannot depend on this since the initialization occurs before this becomes valid (i.e., cannot depend on other instance members).
Can initialize only members of the enclosing class. Because initializer lists are executed before invoking base class constructors, they cannot set base class members.
Constructor body
class Example3 {
T x;
Example3() {
x = value;
}
}
Advantages:
Can utilize construction arguments.
Can be used to perform more complicated initialization, such as cases where the member cannot be initialized via a single expression.
Can use this (i.e., can use other instance members).
Can be used to set base class members.
Disadvantages:
Cannot be used to initialize non-late final nor non-nullable members.
If the class has multiple constructors, initialization would need to be duplicated or initialization code would need to be refactored out (such as, but not limited to, redirecting to a common constructor).
Member is initialized after invoking base class constructors.
If the constructor has a parameter that shadows a member variable, it's easy to accidentally refer to the parameter instead of the member. (See https://github.com/dart-lang/linter/issues/2552 for details.)
There probably are some points I'm forgetting, but I think that should cover the main ones.
Direct, inline initialization occurs first, then initialization lists, then constructor bodies. Also see Difference between assigning the values in parameter list and initialiser list, which explains why this becomes valid only for the later stages of object initialization.
As an example where it matters where members are initialized:
class Base {
Base() {
doSomething();
}
void doSomething() {}
}
class DerivedEarly extends Base {
int? x;
DerivedEarly() : x = 42;
#override
void doSomething() => print(x);
}
class DerivedLate extends Base {
int? x;
DerivedLate() {
x = 42;
}
#override
void doSomething() => print(x);
}
void main() {
DerivedEarly(); // Prints: 42
DerivedLate(); // Prints: null
}

How do you perform inheritance with abstract classes in dart? error : superclass SpanishData doesn't have a zero argument constructor

I'm trying to create an abstract class called SpanishData
And then I want to create another class called alphabet that extends Spanish data
I'm getting an error: the superclass SpanishData doesn't have a zero-argument constructor. How do I fix this?
Here is my code:
abstract class SpanishData{
String englishWord;
String spanishWord;
String mp3;
SpanishData(this.englishWord,this.spanishWord,this.mp3);
void getList (){
}
}
//the alphabet class
import '../SpanishDataAbstract.dart';
class Alphabet extends SpanishData{
#override
void getList(
)
}
You need to refer to the properties of the parent class your class is extending. You can do this using the super keyword.
The super() method on a class constructor allows a subclass to pass arguments and execute the constructor of its superclass.
The code below works:
abstract class SpanishData{
String englishWord;
String spanishWord;
String mp3;
SpanishData(this.englishWord,this.spanishWord,this.mp3);
void getList (){
}
}
class Alphabet extends SpanishData{
// create a constructor of the alphabet class and call the parent constructor
Alphabet(String englishWord, String spanishWord, String mp3) : super(englishWord, spanishWord, mp3);
#override
void getList(){}
}