Original code for MapEntry
class MapEntry<K, V> {
final K key;
final V value;
const factory MapEntry(K key, V value) = MapEntry<K, V>._;
const MapEntry._(this.key, this.value);
}
What's the need to create above factory constructor when you can simply have:
class MapEntry<K, V> {
final K key;
final V value;
const MapEntry(this.key, this.value);
}
Writing the constructor like this effectively makes the class final (Classes are unable to extend from this class). Only generative constructors can be used to call super(). This is as opposed to factory constructors which cannot be used in such a way. As the only generative constructor is the private one named _, extension is prevented. There is the caveat that classes in the same package could extend the class as private members are available to classes in the same package.
By having the factory constructor, instances of MapEntry can still be created even though the default constructor is private.
class MapEntry<K, V> {
final K key;
final V value;
const factory MapEntry(K key, V value) = MapEntry<K, V>._;
const MapEntry._(this.key, this.value);
}
class ExtendableMapEntry<K, V> {
final K key;
final V value;
const ExtendableMapEntry(this.key, this.value);
}
// ---------------
class GoodChild extends ExtendableMapEntry<int, int>{
GoodChild(int i):super(i,i);
}
// Error:
// The constructor 'MapEntry<int, int> MapEntry(int key, int value)' is a
// factory constructor, but must be a generative constructor to be a valid
// superinitializer - line 24
class ImpossibleChild extends MapEntry<int, int>{
ImpossibleChild(int i):super(i,i);
}
Related
I want to do something like the following.
class MySuperClass {
final String s;
MySuperClass(this.s);
factory MySuperClass.from(int a) {
return MySuperClass(a.toString());
}
}
class MySubClass extends MySuperClass {
final int b;
MySubClass(int a, this.b) : super.from(a); // error
}
How would I go about calling the factory constructor of a superclass?
The error given is:
The constructor 'MySuperClass MySuperClass.from(int a)' is a factory constructor, but must be a generative constructor to be a valid superinitializer
As far as I know, you can't call a factory constructor from a subclass. For example, the factory constructor could return a singleton.
Instead make a private constructor MySuperClass._internal and use that in your factory constructor as well as in your subclass.
class MySuperClass {
final String s;
MySuperClass._internal(this.s);
factory MySuperClass(int a) {
print('called');
return MySuperClass._internal(a.toString());
}
}
class MySubClass extends MySuperClass {
final int b;
MySubClass(int a, this.b) : super._internal(a.toString());
}
I am new in Dart(OOP Languange) which it is a bit similar in Java
But this code get me confusion
What is the purpose of colon(:) before the super keyword within SchoolID class that has been inherit with Person class?
Here is the code:
class Person {
String name;
int age;
int height;
Person({this.name, this.age, this.height});
}
class SchoolID extends Person {
int id;
int year;
String name;
SchoolID({this.id, this.year, this.name}) : super(name: name);
}
Another Example ,,, focus on colon the fishmap
AllFish.fromJson(Map<String, dynamic> json)
: fishMap = json.map(
(String k, dynamic v) => MapEntry(
k,
Fish.fromJson(v),
),
);
It's considered as an initializer list which runs before the constructor body, here you're calling the super that means the constructor of your Person class.
It's an initializer. This means the initializer is executed before the constructor body
I have the following inheritance structure in Dart code, and am wondering whether there is a method signature that accounts for both class A and class B for T, so that I have a static check and don't have to typecast. Is this possible?
abstract class A {
String one;
}
abstract class B {
String two;
}
class C implements A, B {
String one;
String two;
}
class D implements A, B {
String one;
String two;
}
void _ohNo<T extends A, B>(T t) {
print(t.one); // valid
print(t.two); // invalid: getter not defined
}
void _ohNo2<T extends A, T extends B>(T t) {} // invalid: T already defined
Could be a workaround:
abstract class Both extends A with B {}
class C implements Both {
String one = '';
String two = '';
}
class D implements Both {
String one = '';
String two = '';
}
void ohNo<T extends Both>(T t) {
print(t.one);
print(t.two);
}
class and const gives a nice possibility to define structured constants. Now I try to extend from one, works ok. Try to use a constant from the inherited class, it works, still I only manage to get through with final instead of const. No big deal in my project, but is it possible to have it const?
class A {
final String name;
final int value;
const A(final String this.name, final this.value);
static const A ONE = const A('One', 1);
}
class B extends A {
const B(final String name, final int val) : super(name, val);
static const B B_ONE = const B('One', 1);//Ok
static const A A_ONE = A.ONE;//Ok
static final B BA_ONE = new B(A.ONE.name, A.ONE.value);//Ok
static const B BA_ONE_CONST = const B(A.ONE);//No B constructor!?!
}
Your B class indeed does not have a constructor that takes a single A instance. You haven't declared one, and you can't do it directly without a little workaround.
The problem is that B extends A, it doesn't just contain an A instance. So, if you want to start with an A instance (like A.ONE) and create a B instance from it, where B extends A and has its own name and value fields, you'll have to extract the name and value from the A to create the new object ... and you can't do property extraction in a const expression. So, that's a no-go.
What you can do is to have a different implementation of B that gets its values directly from an A instance, and then create a constant from that:
class B extends A {
const B(String name, int value) : super(name, value);
const factory B.fromA(A instance) = _SecretB;
...
static const B BA_ONE_CONST = const B.fromA(A.ONE);
}
class _SecretB implements B {
final A _instance;
const _SecretB(this._instance);
String get name => _instance.name;
int get value => _instance.value;
}
If you are the only one using the B.fromA constructor, you could just remove it and call the _SecretB constructor directly. If you want to expose it to other clients of your class, you can make it a const factory constructor like here.
Is it possibly to return a different implementation of as const?
abstract class Foo<T> {
factory Foo(T thing) => const FooImpl(thing); // <= Arguments of a constant creation must be constant expressions
T get thing;
}
class FooImpl<T> implements Foo<T>{
final T thing;
const FooImpl(this.thing);
}
Dart has a delegating factory constructor to allow this
abstract class Foo<T> {
const factory Foo(T thing) = FooImpl;
T get thing;
}
class FooImpl<T> implements Foo<T>{
final T thing;
const FooImpl(this.thing);
}
see also
https://groups.google.com/a/dartlang.org/forum/#!topic/misc/cvjjgrwIHbU and
https://groups.google.com/a/dartlang.org/forum/#!topic/misc/cvjjgrwIHbU