Declaring abstract getters that override implementations from mixins or superclasses results in the getter being undefined when compiled in the dev compiler.
This issue is also present in the reverse, for setters: declaring abstract setters results in the setter being undefined, which actually throws.
Declaring both abstract getters and setters avoids the issue.
Example:
main() {
// Abstract getter declared after concrete impl from mixin
var instance1 = new Class1()..foo = 'bar';
print(instance1.foo); // null
// Abstract getter declared after concrete impl from superclass
// Subclasses of this also fail
var instance2 = new Class2()..foo = 'bar';
print(instance2.foo); // null
// Abstract getter declared in mixin after concrete impl from superclass
var instance3 = new Class3()..foo = 'bar';
print(instance3.foo); // bar
// Abstract getter declared in interface after concrete impl from superclass
var instance4 = new Class4()..foo = 'bar';
print(instance4.foo); // bar
// Mixin overriding abstract getter declared in superclass, which is declared after concrete impl from mixin
var instance5 = new Class5()..foo = 'bar';
print(instance5.foo); // bar
}
abstract class GetterAbstract {
get foo;
}
class GetterConcrete {
var _foo;
get foo => _foo;
set foo(value) => _foo = value;
}
class Class1 extends Object with GetterConcrete {
get foo;
}
class Class2 extends GetterConcrete {
get foo;
}
class Class3 extends GetterConcrete with GetterAbstract {}
class Class4 extends GetterConcrete implements GetterAbstract {}
abstract class _Helper_Class5 extends GetterConcrete {
get foo;
}
class Class5 extends _Helper_Class5 with GetterConcrete {}
This is caused by the setter being redefined for these classes, but not the getter:
list__main.Class2 = class Class2 extends list__main.GetterConcrete {
set foo(value) {
super.foo = value;
}
};
(list__main.Class2.new = function() {
list__main.Class2.__proto__.new.call(this);
}).prototype = list__main.Class2.prototype;
You can see this issue in this ES6 reduced test case:
class A {
get foo() {
return 'foo'
}
set foo(value) {}
}
class B extends A {}
class C extends A {
set foo(value) {}
}
var b = new B();
console.log(b.foo); // 'foo'
var c = new C();
console.log(c.foo); // undefined
We frequently use this pattern of overriding getters in order to update doc comments for subclasses, so it's unfortunate that this is a problem.
This issue is present in Dart 1.24.0 and 1.25.0-dev.1.0
Possibly related: https://github.com/dart-lang/sdk/issues/29935
@kevmoo # 2 DDC issue for Workiva
this still reproduces (both dartdevc and dartdevk)
any update on this @jmesserly ? Is this fixed under Dart 2 DDC?
It is not fixed yet.
ping. wondering if this will be addressed after dart 2 ships.
ping. wondering if this will be addressed after dart 2 ships.
@robbecker-wf sorry it took so long to get back to you, I've been out of the office.
Yeah I would like to see if we can fix this now that Dart 2 has shipped.
Sent out a fix for review: https://dart-review.googlesource.com/c/sdk/+/72073
Hey, thanks @jmesserly !
Most helpful comment
Sent out a fix for review: https://dart-review.googlesource.com/c/sdk/+/72073