I know that you can initialize final variables in a class with something like:
class A {
final num x;
final num y;
final num d;
A(this.x, this.y):
d = sqrt(pow(x, 2) + pow(y, 2));
}
And you can create regular variables inside a constructor like this:
class A {
String z;
A(){
z = 'hello';
}
}
But how do you mix both? Is it possible? What is the syntax?
Simply continue with the constructor right after the initializer, but, since you're going to use curly brackets ({}), you shouldn't use the semi-colon (;):
class A {
final num x;
final num y;
final num d;
String z;
A(this.x, this.y)
: d = sqrt(pow(x, 2) + pow(y, 2))
{
z = 'hello';
}
}
Related
I'm working on some generic list utility functions and there seems to be an issue with the type inference for a generic function when the primary variables are lists. This is demonstrated with the following code:
List<T> combine<T>(List<T> a, List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < a.length && i < b.length; i++) {
list.add(combiner(a[i], b[i]));
}
return list;
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = combine(a, b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
When I use this code as-is, the type inference within the lambda sets a and b to be Object?, which results in the following error message:
The operator '+' can't be unconditionally invoked because the receiver can be 'null'.
Try adding a null check to the target ('!').
Doing what the error message says changes the message to the following:
The operator '+' isn't defined for the type 'Object'.
Try defining the operator '+'.
The issue obviously is that type inference is assigning the parameters to Object? instead of the expected int. This can be worked around by either typing the parameters or explicitly passing the generic type to the function:
final c = combine(a, b, (int a, int b) => a + b);
// OR
final c = combine<int>(a, b, (a, b) => a + b);
However, that's an added level of verbosity that I don't want to have to force the users of these utility functions to have to do (not to mention it will be a support issue when I have to explain to them to do this). Is there a way to change the function signature to make it so type inference works as expected?
This is basically Dart List.fold vs List.reduce type inference, but in your case you could sidestep the problem by making your function an extension method so that T is deduced from the receiver instead of from the arguments:
extension<T> on List<T> {
List<T> combineWith(List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < length && i < b.length; i++) {
list.add(combiner(this[i], b[i]));
}
return list;
}
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = a.combineWith(b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
I have many confusion about Brackets in Dart(Flutter).
Which bracket "(), {}, []" is used for what?
() can group expressions:
var x = (1 + 2) * 3;
or can designate parameter lists for functions:
var getAnswer = () => 42;
int square(int x) => x * x;
or can designate function calls:
var answer = getAnswer();
var squared = square(4);
or is part of the syntax to some keywords. This includes (but is not limited to) if, assert, for, while, switch, catch:
if (condition) {
...
}
assert(condition);
for (var item in collection) {
...
}
while (condition) {
...
}
switch (value) {
...
}
try {
...
} on Exception catch (e) {
...
}
[] by itself creates List literals:
var list = [1, 2, 3];
var emptyList = []; // Creates a List<dynamic>.
or when used on an object, calls operator [], which usually accesses an element of a collection:
var element = list[index];
var value = map[key];
or in a parameter list, specifies optional positional parameters:
int function(int x, [int y, int z]) {
return x + y ?? 0 + z ?? 0;
}
function(1, 2);
or in dartdoc comments, creates linked references to other symbols:
/// Creates a [Bar] from a [Foo].
Bar fooToBar(Foo foo) {
// ...
}
{} can create a block of code, grouping lines together and limiting variable scope. This includes (but is not limited to) function bodies, class declarations, if-else blocks, try-catch blocks, for blocks, while blocks, switch blocks, etc.:
class Class {
int member;
}
void doNothing() {}
void function(bool condition) {
{
int x = 'Hello world!';
print(x);
}
if (condition) {
int x = 42; // No name collision due to separate scopes.
print(x);
}
}
or by itself can create Set or Map literals:
var set = {1, 2, 3};
var emptySet = <int>{};
var map = {'one': 1, 'two': 2, 'three': 3};
var emptyMap = {}; // Creates a Map<dynamic, dynamic>
or in a parameter list, specifies optional named parameters:
int function(int x, {int y, int z}) {
return x + y ?? 0 + z ?? 0;
}
function(1, y: 2);
or creates enumerations:
enum SomeEnumeration {
foo,
bar,
baz,
}
or in Strings is used to disambiguate interpolated expressions:
var foo = 'foo';
var foobar = '${foo}bar';
var s = '${function(1, 2)}';
<> when used as a pair in function or class declarations creates generics:
class GenericClass<T> {
T member;
}
T function<T>(T x) {
// ...
}
or specifies explicit types when using generics:
var map = <String, int>{};
I'm checking out some dart code and looking at this:
AppState.fromJson(Map<String, dynamic> json)
: cartItems = (json['cartItems'] as List)
.map((i) => new CartItem.fromJson(i as Map<String, dynamic>))
.toList();
What's the reasoning behind the colon?
Why is this different from a regular assignment?
You can find more info in the dart tour: https://dart.dev/guides/language/language-tour#classes
If the superclass doesn’t have an unnamed, no-argument constructor, then you must manually call one of the constructors in the superclass. Specify the superclass constructor after a colon (:), just before the constructor body (if any).
Besides invoking a superclass constructor, you can also initialize instance variables before the constructor body runs. Separate initializers with commas.
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}
During development, you can validate inputs by using assert in the initializer list.
Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}
You can also use them to initialize the final variables:
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
I trying make the following overloading inside my class:
class Array extends ListBase<double> {
List<double> l = [];
List<double> operator +=(List<double> b) {
var c = Array.length(l.length);
for(int i = 0; i < l.length; i++) {
c[i] = this[i] * b[i];
}
return c;
}
}
but the Dart compiler show the error message: the string '+=' ins't a user-definable operator. Is there some way to make the overloading of the operator += for others classes types?
Overload only operator +. Dart reuse operators that have a well known semantic meaning such as +=.
Add #override annotation if operator already defined in base class.
I'm trying to figure out how to make static methods in a class in F#. Does anyone have any idea how to do this?
Sure, just prefix the method with the static keyword. Here's an example:
type Example = class
static member Add a b = a + b
end
Example.Add 1 2
val it : int = 3
If you wanted to have static methods in a static class, then use Module
Check out this link, in particular the Modules section:
http://fsharpforfunandprofit.com/posts/organizing-functions/
Here's a module that contains two functions:
module MathStuff =
let add x y = x + y
let subtract x y = x - y
Behind the scenes, the F#
compiler creates a static class with static methods. So the C#
equivalent would be:
static class MathStuff
{
static public int add(int x, int y)
{
return x + y;
}
static public int subtract(int x, int y)
{
return x - y;
}
}