In Dart what is the generated name for a setter method? - dart

If I have a class with a setter defined, how do I reference then generated method as a function from an instance of that class. The spec sort of suggests it would be the id of the variable + '=" (seems daft), but this doesn't parse.
So for example:
class Bar {
set foo(int value) {
//whatever
}
}
typedef F(int value);
void main() {
F f = new Bar().foo=; //Fails, but what should this be??
f(5);
}

The setter is named foo= but this is not something you can reference in the way you want. Even looking at dart:mirrors the MethodMirror (the mirror for object methods including setters) has no way of invoking it. You could easily rewrite this as:
class Bar {
set foo(int value) {
//whatever
}
}
typedef F(int value);
void main() {
Bar b = new Bar();
F f = (int value) => b.foo = value;
f(5);
}

Related

How to pass a static method to a constant constructor?

Docs says
You can use static methods as compile-time constants. For example, you can pass a static method as a parameter to a constant constructor.
But when I tried doing that, I get an error:
Minimal reproducible code:
class Foo {
const Foo(int x);
}
class Bar {
static int get x => 0;
void m() => const Foo(Bar.x); // Error
}
You need to take the documentation more literally:
You can use static methods as compile-time constants. For example, you can pass a static method as a parameter to a constant constructor.
Emphasis mine. What that means is:
class Foo {
const Foo(void Function() func);
}
class Bar {
static void barMethod() {}
}
void main() {
final foo = Foo(Bar.barMethod);
}
Thanks to #Nagual for pointing out the mistake. I was actually calling the method (and passing int) instead of passing the method itself.
This is what I should have done:
class Foo {
const Foo(int Function() cb);
}
class Bar {
static int getX() => 0;
void m() => const Foo(Bar.getX);
}

Use symbols to pass a class member's name?

I'm writing a testing utility function and would like to pass a class member name and get its value. Could I use Symbols for this? My test code looks like this
class Foo {
String a = 'A';
String b = 'B';
static void output(Symbol symbol) {
debugPrint("The value is '$symbol'");
}
}
Foo.output(#a);
I'm trying to get a result like The value is 'A' but I'm getting The value is 'Symbol("a")'?
Getting the value of something by name, where the name is a value, and at runtime, that is reflection.
You need dart:mirrors for that, which isn't available on most platforms.
Better yet, don't do it at all. Dart has first class functions, so you can pass in a function accessing the variable instead:
class Foo {
String a = 'A';
String b = 'B';
static void output(String read(Foo value)) {
debugPrint("The value is '${read(this)}'");
}
}
void main() {
var foo = Foo();
foo.output((f) => f.a);
foo.output((f) => f.b);
}

Limit a generic type argument only to be a int, double or custom class

I trying make the following code but T only can be int, double or a custom class. I couldn't find how to restrict the type in Dart or something that work like where from C#. How can I do that in Dart?
class Array3dG<T> extends ListBase<T> {
List<T> l = List<T>();
Array3dG(List<T> list) {
l = list;
}
set length(int newLength) { l.length = newLength; }
int get length => l.length;
T operator [](int index) => l[index];
void operator []=(int index, T value) { l[index] = value; }
}
There is no way to constrain the type variable at compile-time. You can only have one bound on a type variable, and the only bound satisfying both int and your custom class is Object.
As suggested by #Mattia, you can check at run-time and throw in the constructor if the type parameter is not one of the ones you supprt:
Array3dG(this.list) {
if (this is! Array3dG<int> &&
this is! Array3dG<double> &&
this is! Array3dG<MyClass>) {
throw ArgumentError('Unsupported element type $T');
}
}
This prevents creating an instance of something wrong, but doesn't catch it at compile-time.
Another option is to have factory methods instead of constructors:
class Array3dG<T> {
List<T> list;
Array3dG._(this.list);
static Array3dG<int> fromInt(List<int> list) => Array3dG<int>._(list);
static Array3dG<int> fromDouble(List<double> list) => Array3dG<double>._(list);
static Array3dG<MyClass> fromMyClass(List<MyClass> list) => Array3dG<MyClass>._(list);
...
}
which you then use as Array3dG.fromInt(listOfInt). It looks like a named constructor, but it is just a static factory method (so no using new in front).
You can check at runtime the type with the is keyword:
Array3dG(List<T> list) {
if (list is List<int>) {
//Handle int
}
else if (list is List<double>) {
//Handle double
}
else if (list is List<MyClass>) {
//Handle MyClass
}
else {
throw ArgumentError('Unsupported $T type');
}
}
Note that if you are handling int and double in the same way you can just check for num
You can check the progress of the Union types here: https://github.com/dart-lang/sdk/issues/4938

How to set values of global variables used in function parameters

I can conveniently change opsCount variable directly from inside the function,
because there is only one of that type of variable.
int opsCount = 0;
int jobXCount = 0;
int jobYCount = 0;
int jobZCount = 0;
void doStats(var jobCount) {
opsCount++;
jobCount++;
}
main() {
doStats(jobXCount);
}
But there are many jobCount variables, so how can I change effectively that variable, which is used in parameter, when function is called?
I think I know what you are asking. Unfortunately, the answer is "you can't do this unless you are willing to wrap your integers". Numbers are immutable objects, you can't change their value. Even though Dart's numbers are objects, and they are passed by reference, their intrinsic value can't be changed.
See also Is there a way to pass a primitive parameter by reference in Dart?
You can wrap the variables, then you can pass them as reference:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
}
IntRef opsCount = new IntRef(0);
IntRef jobXCount = new IntRef(0);
IntRef jobYCount = new IntRef(0);
IntRef jobZCount = new IntRef(0);
void doStats(var jobCount) {
opsCount.val++;
jobCount.val++;
}
main() {
doStats(jobXCount);
print('opsCount: $opsCount; jobXCount: $jobXCount; jobYCount: $jobYCount; jobZCount: $jobZCount');
}
EDIT
According to Roberts comment ..
With a custom operator this would look like:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
operator +(int other) {
val += other;
return this;
}
}
void doStats(var jobCount) {
opsCount++;
jobCount++;
}

Reference of Getter/Setter functions

I have the following variable and getter / setter defined in my data model:
class Actor {
int _x;
int get x => _x;
set x(int value) => _x = value;
}
And there is this generic class that requires a getter / setter function pointer
class PropertyItem {
var getterFunction;
var setterFunction;
PropertyItem(this.getterFunction, this.setterFunction);
}
How do i pass a reference of the getter / setter function of X to the PropertyItem class?
// Something like this
var item = new PropertyItem(x.getter, x.setter);
EDIT: Updated with a more clear question
In short, you don't.
Getters and setters are not extractable - they are indistinguishable from just having a field (if you don't do side-effects, of course).
In your example, you could just do:
class Actor {
int x;
}
and get exactly the same effect.
What you want is, for some Actor "actor", to make the functions yourself:
var item = new PropertyItem(() => actor.x, (v) { actor.x = v; });
This proposal about generalized tear offs is approved and will probably implemented soon and allows to closurize getters and setters like:
var item = new PropertyItem(actor#x, actor#x=);
In Dart, the following:
class Foo {
int _offsetX;
int get offsetX => _offsetX;
set offsetX(int ox) => _offsetX = ox;
}
is equivalent to:
class Foo {
int offsetX;
}

Resources