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

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.

Related

Dart - Limit generic constrained type to sub type

i am currently working with Flutter/Dart. I want to implement a generic helper class, which puts a received input value into a generic wrapper, depending on the type.
Here the example code:
class ClassA {}
class ClassB<T> {
ClassB(this.t);
final T t;
}
class ClassC<T extends ClassA? {
ClassC(this.t);
final T t;
}
class ClassD<T> {
ClassD(this.t);
final T t;
Object getWrapper(){
final t = this.t;
return T == ClassA?
? ClassC<T>(t) //<--fails
: ClassB<T>(t);
}
}
Produces:
'T' doesn't conform to the bound 'ClassA?' of the type parameter 'T'.
ClassD is the helper which produces the wrappers. For the wrapper ClassB there is no isdue, but i could not get it to work for the wrapper ClassC. As it constrains its generic type it conflicts with the generic type of the wrapper itself, although i also included a type check there to limit the type to the constrained one.
I am wondering why this won't work and how it could be adjusted to make it work.
I tried to add a type check and adjusted it in various ways like
T == ClassA
or
T is ClassA
also including the local variable t
T == ClassA && t is ClassA

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.

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

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});
}

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(){}
}

Haxe java.lang.Object Equivalent

Haxe allows class inheritance hierarchies
class Honda extends Car {
...
}
is there a common inheritance hierarchy root for all objects? I have a generic container class that could contain any object and I want to be able to declare
var _contents:Object; //Any class instance in _contents
How can I do this?
You can also use {} as a type, which will accept class instances as well as anonymous objects :
var _contents:{};
We also have Dynamic, which basically means "anything" (not only objects, but also primitives like Bool, Int, etc).
If your class is a generic container, you may want to type its content, though, using type parameters:
class Container<T> {
var _contents:T;
public function new(contents:T):Void {
_contents = contents;
}
}
And then:
var arrayContainer = new Container([]);
var stuffContainer = new Container({foo:"bar"});
var classContainer = new Container( new Stuff() );
The inheritance root for classes is Class<T> so the following should work:
var _contents:Class<T>;
However, to store an Enum, you would have to use Enum<T> instead.
From the manual:
There is a special type in Haxe which is compatible with all classes:
Define: Class<T>
This type is compatible with all class types which means that all classes (not their instances) can be assigned to it. At compile-time, Class<T> is the common base type of all class types. However, this relation is not reflected in generated code.
This type is useful when an API requires a value to be a class, but not a specific one. This applies to several methods of the Haxe reflection API.