Dart - Get current type of the class - 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;
}

Related

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.

"'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 the super constructor works in flutter_bloc

In Dart, I understand how super works like this :
class Foo {
Foo(int a, int b) {
//Code of constructor
}
}
class Bar extends Foo {
Bar(int a, int b) : super(a, b);
}
I don't really get what is happening when super is used in the cubit(or blocs) classes of flutter_bloc.
I'm not understanding for example when the CounterCubit class extends Cubit : CounterCubit extends Cubit<CounterState> and the CounterState class can be used as a parameter for the cubit.
class CounterState {
int counterValue;
CounterState({#required this.counterValue});
}
class CounterCubit extends Cubit<CounterState> {
CounterCubit() : super(CounterState(counterValue: 0));
}
The super constructor calls the constructor of the parent class.
The cubit in flutter_bloc is defined as.
abstract class Cubit<State> extends BlocBase<State> {
Cubit(State initialState) : super(initialState);
}
The State is just a generic class type here and can be of any type you want.
You can learn more about generics here
A very simple code for making a counter cubit is.
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
}
The Cubit<int> means your State here is of type int and super(0) sets the initial value state value to "0" as your value is type int. So essentially the super constructor of a cubit takes in the value of the initial state.
In your case:
class CounterState {
int counterValue;
CounterState({#required this.counterValue});
}
class CounterCubit extends Cubit<CounterState> {
CounterCubit() : super(CounterState(counterValue: 0));
}
The Cubit<CounterState> means your State here is of type CounterState (which is a class you declared yourself above) and super(CounterState(counterValue: 0)) initializes an object with counterValue=0 and that object is passed as the initial state via super constructor.
I hope this clarifies your question. Do let me know if my explanation was not clear enough for you

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

Call parent constructor with this as argument

I have a class that takes one of its subclasses as an argument. When constructing that subclass, I want to be able to use this as the value of that argument:
class A(val b: B)
class B extends A(this)
However, this fails to compile
this can be used only in a class, object, or template
[error] class B extends A(this)
[error] ^
Is there any way to get around this? I'm pretty sure that a pattern like this can be written in Java.
I'm not so sure about the last statement:
public class MyClass {
static class A {
A(B b) {
System.out.println(b.value);
}
}
static class B extends A {
String value;;
B() {
super(this);
value = "x";
}
}
public static void main(String args[]) {
new B();
}
}
gives the following error:
/MyClass.java:10: error: cannot reference this before supertype constructor has been called
super(this);
^
There is no good reason to attempt to let the this reference escape the scope of the constructor before the object itself has been constructed. Refactor it.