Dart - ArtemMikhaylov/my_flutter_notes GitHub Wiki
Page navigation
- Equals
- Access identifiers
- Variables
- Optional parameters
- Strings
- Async
- Exceptions
- Interfaces & Abstract classes
- Constructors
- Initializer lists
- Factory constructors
- Null-aware operators
- Collections
- Functional programming
- Cascades
https://api.dart.dev/stable/2.7.1/dart-core/Object/operator_equals.html
== - The default behavior for all Objects is to return true if and only if this and other are the same object.
If a subclass overrides the equality operator it should override the hashCode method as well to maintain consistency.
https://api.dart.dev/stable/2.7.1/dart-core/Object/hashCode.html
https://stackoverflow.com/a/18428776/3165400
- everything is public by default
- private is prefix
_to the name
What is good about it, is if you will decide to make variable private, and add a getter, the outside code won't be changed, still the same bicycle.speed (no need to change it to bicycle.getSpeed() or bicycle.speed()like in java) because ofget` identifier. (And the same with setters?)
int _speed = 0;
int get speed => _speed;The classic getters and setters in Dart (set and get identifiers are in use)
class MyClass {
int _aProperty = 0;
int get aProperty => _aProperty;
set aProperty(int value) {
if (value >= 0) {
_aProperty = value;
}
}
}Another example. You can also use a getter to define a computed property:
class MyClass {
List<int> _values = [];
void addValue(int value) {
_values.add(value);
}
// A computed property.
int get count {
return _values.length;
}
}- Uninitialized variables (even numbers) have the value
null - If you know that a variable's value won't change, you can use
finalinstead ofvar
Optional positional parameters link
//b, c, d, and e are optional parameters (always last in a function’s parameter list)
int sumUpToFive(int a, [int b, int c, int d, int e]) {//...}Their default value is null unless you provide another default value:
int sumUpToFive(int a, [int b = 2, int c = 3, int d = 4, int e = 5]) {//...}Optional named parameters
void printName(String firstName, String lastName, {String thirdName}) {
print('$firstName $lastName ${thirdName?? ''}');
}or with default value
void printName(String firstName, String lastName, {String suffix = ''}) {
print('$firstName $lastName $suffix');
}For each cycle?
for (var object in flybyObjects) {
print(object);
}A shorthand => (arrow) syntax is handy for functions that contain a single statement. This syntax is especially useful when passing anonymous functions as arguments:
//As I understand: where() takes function as parameter,
//in this case we declare anonymus function with 'name' parameter
//(we skip Type of name (WTF? how this even considered as good thing for any language?!?))
//and then we call 'forEach' for result returned by 'where'.
//'forEach' it's like reactive way of
//for each cycle, wich takes function as parameter, (and 'print' takes object as parameter?)
flybyObjects.where((name) => name.contains('turn')).forEach(print);Constructor with no body is valid in Dart
Bicycle(this.cadence, this.speed, this.gear);Instead of constructors overloading dart has named constructors:
// Constructor, with syntactic sugar for assignment to members.
Spacecraft(this.name, this.launchDate) {
// Initialization code goes here.
}
// Named constructor that forwards to the default one.
Spacecraft.unlaunched(String name) : this(name, null);And coustructors with optional named parameters
Rectangle({this.origin = const Point(0, 0), this.width = 0, this.height = 0});Optional parameters in constructors have to be supplied with default values. The specified default must be a compile-time constant.
Using this with named parameters:
Property names become the names of the parameters:
MyColor({this.red, this.green, this.blue});For optional parameters, default values work as expected:
MyColor([this.red = 0, this.green = 0, this.blue = 0]);
// or
MyColor({this.red = 0, this.green = 0, this.blue = 0});Redirecting constructors. A redirecting constructor’s body is empty.
class Automobile {
String make;
String model;
int mpg;
// The main constructor for this class.
Automobile(this.make, this.model, this.mpg);
// Delegates to the main constructor.
Automobile.hybrid(String make, String model) : this(make, model, 60);
// Delegates to a named constructor
Automobile.fancyHybrid() : this.hybrid('Futurecar', 'Mark 2');
}Calling super constructors
class Foo {
Foo(int a, int b) {
//Code of constructor
}
Foo.named(int c, int d) {
//Code of named constructor
}
}
class Bar extends Foo {
Bar(int a, int b) : super(a, b);
}
class Baz extends Foo {
Baz(int c, int d) : super.named(c, d);
}If you want to initialize instance variables in the subclass, the super() call must be last in an initializer list.
class CBar extends Foo {
int c;
CBar(int a, int b, int cParam) :
c = cParam,
super(a, b);
}If your class produces objects that never change, you can make these objects compile-time constants.
class ImmutablePoint {
const ImmutablePoint(this.x, this.y);
final int x;
final int y;
static const ImmutablePoint origin =
ImmutablePoint(0, 0);
}https://dart.dev/codelabs/dart-cheatsheet#initializer-lists
Sometimes when you implement a constructor, you need to do some setup before the constructor body executes. For example, final fields must have values before the constructor body executes. Do this work in an initializer list, which goes between the constructor’s signature and its body:
Honestly don't understand why we just don't do the same shit in the constructor body.
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}The initializer list is also a handy place to put asserts, which run only during development:
NonNegativePoint(this.x, this.y)
: assert(x >= 0),
assert(y >= 0) {
print('I just made a NonNegativePoint: ($x, $y)');
}Dart supports factory constructors, which can return subtypes or even null.
So we create a subclass of Shape like we create a Shape with parameter. https://codelabs.developers.google.com/codelabs/from-java-to-dart/#3
abstract class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle(2);
if (type == 'square') return Square(2);
throw 'Can\'t create $type.';
}
num get area;
}final circle = Shape('circle');
final square = Shape('square');class Orbiter extends Spacecraft {
num altitude;
Orbiter(String name, DateTime launchDate, this.altitude)
: super(name, launchDate);
}Добавляет к классу методы и функции другого класса
class Piloted {
int astronauts = 1;
void describeCrew() {
print('Number of astronauts: $astronauts');
}
}
class PilotedCraft extends Spacecraft with Piloted {
// ···
}https://dart.dev/guides/language/language-tour#abstract-classes
Dart has no interface keyword. Instead, all classes implicitly define an interface. Therefore, you can implement any class.
class MockSpaceship implements Spacecraft {
// ···
}https://dart.dev/samples#async https://dart.dev/codelabs/async-await
С использованием async await подхода
const oneSecond = Duration(seconds: 1);
// ···
Future<void> printWithDelay(String message) async {
//Ждйм колбэк через секунду (наверное пустой коблэк,
//т.е. как будто (а может так и есть) стартуется побочный поток, который усыпляется на секунду,
//и следом возвращает колбэк, и мы двигаемся дальше по коду в основном потоке)
await Future.delayed(oneSecond);
print(message);
}The method above is equivalent to:
//здесь синтаксис не понятен. Видимо из за того чо весь код после return,
Future<void> printWithDelay(String message) {
return Future.delayed(oneSecond).then((_) {
print(message);
});
}
//я бы лучше написал вот так вот (надо будет проверить эквивалентно ли это)
//так гораздо понятнееб '.then() - это по сути колбэк в который мы передаем анонимную
//функцию? но что значит нижнее подчеркивание в параметрах?
Future<void> printWithDelay(String message) {
Future future = Future.delayed(Duration(seconds: 1)).then((_) {
print(message);
});
return future;
}Это вообще что такое?
Stream<String> report(Spacecraft craft, Iterable<String> objects) async* {
for (var object in objects) {
await Future.delayed(oneSecond);
yield '${craft.name} flies by $object';
}
}-
https://dart.dev/guides/language/effective-dart/usage#error-handling
-
At Dart, methods don’t declare which exceptions they might throw, and you aren’t required to catch any exceptions.
-
tryandfinallyare the same as in Java -
Dart provides Exception and Error types, but you’re allowed to throw any non-null object:
throw Exception('Something bad happened.');
throw 'Waaaaaaah!';Use the 'on' keyword to filter for specific exceptions by type, and the catch keyword to get a reference to the exception object
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}If you can’t completely handle the exception, use the rethrow keyword to propagate the exception:
try {
breedMoreLlamas();
} catch (e) {
print('I was just trying to breed llamas!.');
rethrow;
}https://dart.dev/codelabs/dart-cheatsheet#string-interpolation
$wisth and $height - variables, ${origin.x}, ${origin.y} - variables of object origin
'Origin: (${origin.x}, ${origin.y}), width: $width, height: $height''${3 + 2}' //5
'${"word".toUpperCase()}' //WORD
'$myObject' //The value of myObject.toString()'Can\'t create $type.'
//or
"Can't create $type."https://dart.dev/codelabs/dart-cheatsheet#null-aware-operators
??= - assignment operator, which assigns a value to a variable only if that variable is currently null.
//the same as: if(dog == null) dog = new Dog();
dog ??= new Dog();?? - returns the expression on its left unless that expression’s value is null, in which case it evaluates and returns the expression on its right
print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.Conditinal property access https://dart.dev/codelabs/dart-cheatsheet#conditional-property-access
//the same as: (myObject != null) ? myObject.someProperty : null
myObject?.someProperty
//the same as: if(myObject != null)
// if(myObject.someProperty != null)
// myObject.someProperty.someMethod();
myObject?.someProperty?.someMethod()https://dart.dev/codelabs/dart-cheatsheet#collection-literals
final aListOfStrings = ['one', 'two', 'three'];
final aSetOfStrings = {'one', 'two', 'three'};
final aMapOfStringsToInts = {
'one': 1,
'two': 2,
'three': 3,
};var image = {
'tags': ['saturn'],
'url': '//path/to/saturn.jpg'
};Dart’s type inference can assign types to these variables for you. In this case, the inferred types are List<String>, Set<String>, and Map<String, int>.
Or you can specify the type yourself:
final aListOfInts = <int>[];
final aSetOfInts = <int>{};
final aMapOfIntToDouble = <int, double>{};Specifying types is handy when you initialize a list with contents of a subtype, but still want the list to be List:
final aListOfBaseType = <BaseType>[SubType(), SubType()]https://dart.dev/codelabs/iterables#what-is-an-iterable
List and Set are Iterable; A Map uses a different data structure internally. Elements of a Map can also be read as Iterable objects by using the map’s entries or values property.
//creating List of int with Iterable reference to it
Iterable<int> iterable = [1, 2, 3];
//this is not possible!
int value = iterable[1];
//this is possible
int value = iterable.elementAt(1);Reading elements using a for-in loop.
for (var element in iterable) {
print(element);
}
//(Iterator: An object used by for-in to read elements from an Iterable object.)Using firstWhere() to find the first element that satisfies certain conditions
//This method requires you to pass a predicate
//(“predicate” just means a function that return true or false.)
//As an expression: The test code has one line that uses arrow syntax (=>).
String element = iterable.firstWhere((element) => element.length > 5);
//As a block: The test code has multiple
//lines between brackets and a return statement.
items.firstWhere((element) {
return element.length > 5;
})1;
//As a function: The test code is in an external function
//that’s passed to the firstWhere() method as a parameter.
items.firstWhere(predicate);If no element satisfies the test predicate and the orElse parameter isn’t provided, then firstWhere() throws a StateError.
//using orElse parameter
items.firstWhere(
(element) => element.length > 10,
orElse: () => 'None!',
);Checking conditions
return items.every((element) => element.length >= 5);
//which is equivalent to this
for (var item in items) {
if (item.length < 5) {
return false;
}
}
return true;Similar to every: any:
items.any((element) => element.contains('a'))/**
* Returns the value for the given [key] or null if [key] is not in the map.
*
* Some maps allow keys to have `null` as a value.
* For those maps, a lookup using this operator cannot distinguish between a
* key not being in the map and the key having a `null` value.
* Methods like [containsKey] or [putIfAbsent] can be used if the distinction
* is important.
*/
V operator [](Object key);In functional programming you can do things like link:
- Pass functions as arguments.
- Assign a function to a variable.
- Deconstruct a function that takes multiple arguments into a sequence of functions that each take a single argument (also called currying).
- Create a nameless function that can be used as a constant value (also called a lambda expression; lambda expressions were added to Java in the JDK 8 release).
In Dart, even functions are objects and have a type, Function.
The following example uses imperative (not functional-style) code:
//'a' * length - yeah, you can do that,
//as a result, 'a' will be in this place of a string a 'length' times!
String scream(int length) => "A${'a' * length}h!";
main() {
final values = [1, 2, 3, 5, 10, 50];
//imperative style
for (var length in values) {
print(scream(length));
}
}The same in functional style
values.map(scream).forEach(print);//skip - skip one object, e.g. start from second object
//take - take three objects
values.skip(1).take(3).map(scream).forEach(print);https://dart.dev/codelabs/dart-cheatsheet#cascades
//invokes someMethod() on myObject,
//but the result of the expression isn’t the return value — it’s a reference to myObject!
myObject..someMethod()
//This way you can do smth like this
myObject
..name = 'Nick'
..age = 23
..commit();