вторник, 27 апреля 2021 г.

Composite

abstract class IShape {
  void getArea();
}

class Shape implements IShape {
  double area;

  Shape(this.area);

  @override
  void getArea() {
    print(area);
  }
}

class Rect extends Shape {
  double w, h;

  Rect(this.w, this.h) : super(w * h);
}

class Circle extends Shape {
  double radius;

  Circle(this.radius) : super(3.14 * radius * radius);
}

class Canvas implements IShape {
  var shapes = <IShape>[];

  @override
  void getArea() {
    for (var shape in shapes) {
      shape.getArea();
    }
  }
}

void main() {
  final canvas = Canvas();
  canvas.shapes = [
    Rect(5, 5),
    Circle(3),
  ];
  canvas.getArea();
}

воскресенье, 25 апреля 2021 г.

Template Method

abstract class SoundSystem {
  void makeSound() {
    print(getSound());
  }

  String getSound();
}

class DVDPlayer extends SoundSystem {
  @override
  String getSound() {
    return 'Play DVD disk';
  }
}

class Radio extends SoundSystem {
  @override
  String getSound() {
    return 'Play radio station';
  }
}

void main() {
  final systems = <SoundSystem>[
    DVDPlayer(),
    Radio(),
  ];

  for (var system in systems) {
    system.makeSound();
  }
}

Adapter

abstract class ITemperatureAdapter {
  String getTemperature();
}

class CelsiusAdapter implements ITemperatureAdapter {
  double cel;
  CelsiusAdapter(this.cel);

  @override
  String getTemperature() {
    return 'Fahrenheit: ${C2F(cel)}';
  }

  double C2F(double cel) {
    return (cel * 9 / 5) + 32;
  }
}

class FahrenheitAdapter implements ITemperatureAdapter {
  double far;
  FahrenheitAdapter(this.far);

  @override
  String getTemperature() {
    return 'Celsius: ${F2C(far)}';
  }

  double F2C(double far) {
    return (far - 32) * 5 / 9;
  }
}

void main() {
  printTemp(CelsiusAdapter(10));
  printTemp(FahrenheitAdapter(104));
}

void printTemp(ITemperatureAdapter adapter) {
  print(adapter.getTemperature());
}

суббота, 24 апреля 2021 г.

Singleton

//Classic way
class Manager1 {
  static Manager1? _instance; //null

  Manager1._internal() {
    print('new instance of Manager1 constructed');
  }

  static Manager1? getInstance() {
    _instance ??= Manager1._internal();
    return _instance;
  }
}


//Dart way
class Manager2 {
  static final Manager2 _instance = Manager2._internal();

  Manager2._internal() {
    print('new instance of Manager2 constructed');
  }

  factory Manager2() {
    return _instance;
  }
}


void main() {

  final m1 = Manager1.getInstance(); //new instance of Manager1 constructed
  final m2 = Manager1.getInstance();

  final m3 = Manager2(); //new instance of Manager2 constructed
  final m4 = Manager2();

}

вторник, 13 апреля 2021 г.

Asynchronous

//Dart is a single-threaded language.
//Future - promise to give you the value later.
void main() {

  //Callbacks
  print('Start'); //1
  Future<int>.delayed(Duration(seconds: 3), () => 7)
      .then(
        (value) => print('Value: $value'), //3
  )
      .catchError(
        (error) => print('Error: $error'),
  )
      .whenComplete(
    //run after value or error
        () => print('Ready!'), //4
  );
  print('End'); //2

  //async-await
  print('Start2'); //synchronous function
  main2(); //asynchronous function - promise to give you the value later.
  print('End2'); //synchronous function

  //try-catch - error handling
  print('Start3');
  main3();
  print('End3');

}

//asynchronous function
Future<void> main2() async {
  final value = await Future<int>.delayed(Duration(seconds: 2), () => 7);
  //the rest of the function won’t run until the future completes
  print('Value2: $value');
  print('Ready2!');
}

//try-catch - error handling
Future<void> main3() async {
  try {
    //throw Exception('error'); //error testing
    final value = await Future<int>.delayed(Duration(seconds: 1), () => 7);
    //the rest of the function won’t run until the future completes
    print('Value3: $value');
  } catch (error) {
    print(error);
  } finally {
    print('Ready3!'); //run after value or error
  }
}

понедельник, 12 апреля 2021 г.

OOP

//Inheritance, Interfaces, Polymorphism, mixins
void main() {

  //Inheritance, "is, is! (is not)"-operators
  //Only one class can be inherited
  final st1 = Student('Tom', 'USA', 'German');
  print('Type: ' + st1.runtimeType.toString());
  print('isObject: ' + (st1 is Object).toString());
  print('isPerson: ' + (st1 is Person).toString());
  print('isStudent: ' + (st1 is Student).toString());
  print('isNotTeacher: ' + (st1 is! Teacher).toString());
  final st2 = Student('Mike', 'UK', 'Math');
  final tch1 = Teacher('Fred', 'France', 'Art');

  //Polymorphism - A Student is a Person
  //But prefer composition over inheritance!
  //It’s more of what an object HAS,
  //than what an object IS.
  final persons = <Person>[st1, st2, tch1];
  for (var person in persons) {
    print(person);
  }

  //Abstract classes - can't instantiate
  //final sh1 = Shape(); //error!
  final sq1 = Square(size: 5);
  final cr1 = Circle(radius: 5);
  //Polymorphism - Square and Circle are Shapes
  final shapes = <Shape>[sq1, cr1];
  for (var shape in shapes){
    if (shape is Square){
      print('I am ${shape.runtimeType}! With size: ${shape.size}. My area is: ${shape.area()}');
    } else if (shape is Circle){
      print('I am ${shape.runtimeType}! With radius: ${shape.radius}. My area is: ${shape.area()}');
    } else {
      print('I am ${shape.runtimeType}! My area is: ${shape.area()}');
    }
  }

  //Interfaces
  //Many interfaces cam be inherited
  final iDrawable sp1 = Sprite();
  sp1.draw();
  (sp1 as iUpdatable).update(); //as - casting

  //Factory constructor -
  //to keep the implementation details separate from the business logic.
  //Nothing changes here
  final someSubClass = FactoryClass();
  someSubClass.interface();

  //Mixins
  //Many mixins cam be inherited
  final mDrawable sp2 = Sprite1();
  sp2.draw();
  (sp2 as mUpdatable).update();
  final mUpdatable ph1 = Physics();
  ph1.update();

  //Extension methods
  st1.hi();
  st2.hi();
  print(5.doubled);
  print('Monday is a workday: ${Days.Monday.isWorkDay}');

}

//Parent (super) class
class Person {
  Person(this.name, this.country);
  String name;
  String country;
  String get info => 'My name is $name, I am from $country.';

  @override
  String toString() => info;
}

//Inheritance, "extends" keyword
//override properties and methods, super
//Child (sub) class
class Student extends Person {
  Student(String name, String country, this.subject) : super(name, country);
  String subject;

  @override
  String get info => '${super.info} I am learning $subject.';
}
class Teacher extends Person {
  Teacher(String name, String country, this.subject) : super(name, country);
  String subject;

  @override
  String get info => '${super.info} I am teaching $subject.';
}

//Abstract classes
abstract class Shape {
  Point center = Point();
  double area(); //abstract method
}
class Square extends Shape {
  Square({required this.size});
  final double size;
  @override //implements abstract methods
  double area() => size * size;
}
class Circle extends Shape {
  Circle({required this.radius});
  final double radius;
  @override //implements abstract methods
  double area() => 3.14 * radius * radius;
}
class Point{
  int x = 0, y = 0;
}

//Interfaces, "implements" keyword
//When you extend GameObj, Sprite has access to any methods or variables in GameObj.
//If Sprite implements iDrawable and iUpdatable, Sprite must provide its own version
//of all methods and variables in iDrawable and iUpdatable.
class GameObj {
}
abstract class iDrawable { //Interface
  late Point center; //late - initialises when instantiates
  void draw();
}
abstract class iUpdatable { //Interface
  void update();
}
class Sprite extends GameObj implements iDrawable, iUpdatable {
  @override
  Point center = Point();
  @override
  void draw() { //need implementation
  }
  @override
  void update() { //need implementation
  }
}

//Factory constructor, can return subclass!!!
//to keep the implementation details separate from the business logic
//Changes live here
abstract class FactoryClass { //Interface - see to user
  factory FactoryClass() => SubClass1();
  //factory FactoryClass() => SubClass2();
  //factory FactoryClass() => SubClass3();
  void interface();
}
class SubClass1 implements FactoryClass { //Concrete class - hide from user
  @override
  void interface() {
    print('I am $runtimeType');
  }
}

//Mixins, "with" keyword
//You can use concrete or abstract class as a mixin,
//but "mixin" keyword indicates that...
mixin mDrawable { //this class can only be used as mixin
  void draw() {
    print('Default draw');
  }
}
mixin mUpdatable { //this class can only be used as mixin
  void update() {
    print('Default update');
  }
}
class Sprite1 extends GameObj with mDrawable, mUpdatable {
  //do not need implementation of the draw and update methods
}
class Physics extends GameObj with mUpdatable{
  //we can use realisation from mixin class
}

//Extension methods
//we can extend String, int, ...
//name MyExt is optional
extension _MyExt on Person {
  void hi(){
    print('Hi $name');
  }
}
extension on int {
  int get doubled {
    return this * this;
  }
}

enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
extension on Days {
  bool get isWorkDay {
    switch (this) {
      case Days.Monday:
      case Days.Tuesday:
      case Days.Wednesday:
      case Days.Thursday:
      case Days.Friday:
        return true;
      case Days.Saturday:
      case Days.Sunday:
        return false;
      default:
        throw Exception('Unknown weekday $this');
    }
  }
}

пятница, 9 апреля 2021 г.

Functional

//Higher order methods
//map(), where(), every(), reduce(), fold() and sort().
void main() {

  var numbers = [1, 2, 3, 4, 5];

  //map()
  var sq1 = [];
  for(var element in numbers){
    sq1.add(element * element);
  }
  print(sq1);

  final sq2 = numbers.map((element) => element * element).toList();
  print(sq2);

  //where() - filter
  var even1 = [];
  for(var element in numbers){
    if (element.isEven) {
      even1.add(element);
    }
  }
  print(even1);

  final even2 = numbers.where((element) => element.isEven).toList();
  print(even2);

  //every()
  bool? isGood1;
  for(var element in numbers){
    if (element == 3) {
      isGood1 = false;
      break;
    }
    isGood1 = true;
  }
  print(isGood1);

  final isGood2 = numbers.every((element) => element != 3);
  print(isGood2);

  //reduce()
  var sum1 = 0;
  for (var element in numbers) {
    sum1 += element;
  }
  print(sum1);

  final total1 = numbers.reduce((value, element) => value + element);
  print(total1);

  //fold()
  var strings = ['a', 'bb', 'ccc', 'dddd', 'eeeee'];
  var sum2 = 0;
  for (var element in strings) {
    sum2 += element.length;
  }
  print(sum2);

  final total2 = strings.fold(0, (value, element) => (value as int) + element.length);
  print(total2);

  //sort()
  var list1 = [3, 5, 1, 4, 2];
  list1.sort();
  print(list1);

  //Comparable
  var list2 = ['c', 'a', 'b'];
  list2.sort();
  print(list2);

  //Comparator
  var list3 = ['ccc', 'a', 'bb'];
  list3.sort((prev, next) => prev.length.compareTo(next.length));
  print(list3);

  //Custom Types
  var points = [Point(3, 1), Point(1, 3), Point(2, 2)];
  //Comparable
  points.sort();
  print(points);
  //Comparator
  points.sort((prev, next) => prev.y.compareTo(next.y));
  print(points);

  //reversed property
  var reversedNumbers = numbers.reversed.toList();
  print(reversedNumbers);

  //Combining methods
  final seven = numbers.where((element) => (element % 2) == 0)
      .where((element) => element == 4)
      .map((e) => e + 3).first;
  print(seven);

}

class Point implements Comparable<Point>{
  Point(this.x, this.y);
  final x;
  final y;

  @override
  bool operator ==(Object other) {
    return (other is Point) && other.x == x && other.y == y;
  }

  //Comparable
  //The function must return an integer.
  // If the result is negative, the first value will be placed before the second value.
  // Otherwise, the second value will appear before the first value in the sorted List.
  // If the result is 0, it means both values are equal in the ordering.
  @override
  int compareTo(Point other) {
    return x - other.x;
  }

  @override
  int get hashCode => x.hashCode ^ y.hashCode;

  @override
  String toString() {
    return 'Point (x: $x, y: $y)';
  }
}

четверг, 8 апреля 2021 г.

Collections

//List, Set, Map
void main() {

  //List
  var cities = []; // List<dynamic>
  var cities0 = <String>[]; // List<String>
  List<String> cities1 = ['London', 'Moscow', 'Minsk']; //explicit
  var cities2 = ['London', 'Moscow', 'Minsk'];  //implicit
  cities2[1] = 'Paris'; //change element
  cities2.add('Berlin'); //add element
  cities2.remove('Minsk'); //delete element
  print(cities2);

  //iterate list - access to elements
  for (var city in cities2) { //for-in loop
    print(city); //access by iterator
  }
  for (var i = 0; i < cities2.length; i++) { //for loop
    print(cities2[i]); //access by index
  }
  cities2.forEach((city) => print(city)); //forEach method
  cities2.forEach(print); //the same

  //properties and methods of lists
  var ints = [1, 3, 5, 7, 9];
  print(ints.length);
  print(ints.isEmpty);
  print(ints.isNotEmpty);
  print(ints.first);
  print(ints.last);
  ints.insert(1, 2);
  print(ints.removeAt(1));
  print(ints.contains(3));
  print(ints.indexOf(3));
  ints.clear();
  print(ints);

  //list mutability
  final vec1 = [1, 2, 3]; //runtime const
  //vec1 = [4, 5, 6]; //error!!!
  vec1[0] = 9; //OK!
  const vec2 = [4, 5, 6]; //compile time const
  //vec2[0] = 9; //error!!!
  final vec3 = const[4, 5, 6]; //the same
  //vec3[0] = 9; //error!!!
  final vac4 = List.unmodifiable([DateTime.now(), DateTime.now()]);
  //vec4[0] = 9; //error!!!

  //Sets - no duplicates, unordered
  Set<String> set = {};
  var set0 = <String>{}; //empty Set<String>
  var set1 = {'Italy', 'UK', 'Russia'}; //Set<String>
  set1.add('Italy');
  set1.addAll({'Spain', 'France'});
  print(set1);
  set1.remove('Italy');
  print(set1);
  //properties and methods
  print(set1.length);
  print(set1.first);
  print(set1.last);
  print(set1.isEmpty);
  print(set1.isNotEmpty);
  print(set1.elementAt(0));
  print(set1.contains('UK'));
  //set1.clear();
  var set2 = {'Russia', 'Belarus'};
  print(set1.union(set2));
  print(set1.intersection(set2));
  print(set1.difference(set2));
  //iterate
  for (var s in set1) {
    print(s);
  }
  set1.forEach(print);
  //...

  //Maps, 'as'-operator
  var map = {}; //Map<dynamic, dynamic>
  Map<String, int> map0 = {};
  var map1 = <String, int>{};
  var map2 = {'Tom': 34, 'Mike': 35,}; //key : value

  Map<String, Object> person = {
    'name': 'Vasili',
    'age': 48,
  };
  print(person['name']); //access to value by key
  person['name'] = 'Tom'; //change value
  person['man'] = true; //add new pair
  person.remove('man'); //delete pair
  print(person);
  print(person.keys);
  print(person.values);
  //iterate
  for (var e in person.entries) {
    print(e);
    print('key: ${e.key} - value: ${e.value}');
  }
  for (var k in person.keys) {
    print(k); //keys
  }
  for (var k in person.keys) {
    print(person[k]); //value by keys
  }
  for (var v in person.values) {
    print(v); //values
  }
  person.forEach((key, value) {print('$key -> $value'); });
  //properties and methods
  print(person.length);
  print(person['name'].runtimeType);
  var name = person['name'] as String; //casting Obj -> Str
  print(name.toUpperCase());
  print(person.isEmpty);
  print(person.isNotEmpty);
  print(person.containsKey('name'));
  print(person.containsValue(48));

  //Null - no value
  print('job: ${person['job']}'); //null

  //Nested Collections
  var students = [ //List<Maps<String, Object>>
    //list
    {
      //map
      'name': 'Mike',
      'marks': [5.0, 2.7, 3.6], //list
    },
    {
      'name': 'Tom',
      'marks': [3.0, 1.7, 0.6],
    },
    {
      'name': 'Fred',
      'marks': [7.0, 4.7, 5.6],
    },
  ];
  for (var student in students) {
    print(student.runtimeType);
    print(student.entries);
    final marks = student['marks'] as List<double>; //casting Obj -> List<dbl>
    print(marks.length);
  }

  //Collection-if
  const addBlue = false;
  const addRed = true;
  const colors = [
    'grey',
    'green',
    if (addBlue) 'blue',
    if (addRed) 'red',
  ];
  print(colors);

  const rates = [3.0, 4.0, 2.0];
  final students2 = {
    'name': 'Bob',
    if (rates.length > 3) 'rates': rates,
  };
  print(students2);

  //Collection-for
  const extraColors = ['yellow', 'black'];
  var colors1 = [
    'grey',
    'green',
    'red',
    for (var color in extraColors) color,
  ];
  print(colors1);
  colors1.addAll(extraColors);
  print(colors);

  //Spread operator (..., ...?) - expand elements
  final colors2 = [
    'grey',
    'green',
    'red',
    ...extraColors,
    if (true) ...['tmp1', 'tmp2']
  ];
  print(colors2);

  final students3 = {
    'name': 'Bob',
    if (true) ...{
      'rates': rates,
      'job': true,
    }
  };
  print(students3);

  //...?
  List<String>? pens;
  final draw = ['paper', ...?pens];

  //Copying = reference to collection
  final list = [1, 2, 3];
  final copy1 = list; //copy reference
  copy1[0] = 0;
  print('list: $list'); //list: [0, 2, 3]
  print('copy1: $copy1'); //copy1: [0, 2, 3]

  final copy2 = [
    for (var item in list) item, //copy values
  ];
  copy2[0] = 1;
  print('list: $list'); //list: [0, 2, 3]
  print('copy2: $copy2'); //list: [1, 2, 3]

  final copy3 = [...list];
  copy3[0] = 6;
  print('list: $list'); //list: [0, 2, 3]
  print('copy3: $copy3'); //list: [6, 2, 3]

}

среда, 7 апреля 2021 г.

Nullability

//Sound Null Safety >= Dart 2.12!
void main() {

  //old - need check for null
  const pers = {
    'name': 'Tom',
  };
  if (pers['age'] != null) {
    print(pers['age']);
  }

  //Not Nullable and Nullable types (int, int?, ..)
  //all is "Object?"!!! (root class)
  int x1; //int - not nullable type by default (cannot be null)
  //print(x1); //error!!! - must be assigned before used!!!
  int? x2 = null; //int? - nullable type (can be null)
  int? x3; //null by default
  print(x3); //it is okay - null

  //new Flow Analysis
  if (5 > 3) { //if-else condition
    x1 = 1; //dart check - x1 has value
  } else {
    x1 = 2; //dart check - x1 has value
  }
  //x1 = (5 > 3) ? 1 : 2; //ternary operator
  print(x1); //dart check - x1 has value

  //Promotion
  x2 = 2;
  if (x2 != null) { //if null-check
    //dart check - x2 has value
    print(x2); //x2 promote! to non nullable
  }

  //Null-aware operators
  //Assertion operator (postfix !) make non-nullable
  //equivalent to casting from Object? to Object
  int x = 42;
  int? mayBe;
  if(x > 0){
    mayBe = x;
  }
  //int value = mayBe; //error!
  //int? value0 = mayBe as int; //OK! - casting from int? to int
  //assert(mayBe! != null); //assert null-check
  int? value1 = mayBe!; //Ok! - assertion (!) operator
  print(value1); //42

  //null-check - ternary operator
  mayBe = null;
  var val = (mayBe == null) ? 0 : mayBe;
  print(val); //0

  //if-null operator (??)
  mayBe = null;
  var val1 = mayBe ?? 0; //if mayBe == null, use 0 for val1
  print(val1); //0

  //null-conditional assign operator (??=)
  mayBe = null;
  //mayBe = mayBe ?? 0; // x = x + 1 >>> x += 1 >>> ??=
  mayBe ??= 0; //if mayBe == null, assign 0 to it.
  print(mayBe);

  //Null Safety with collections
  var cities1 = <String?>['London', 'Paris', null]; //items can be null
  print(cities1);
  for (var city in cities1){
    if (city != null) { //city promote to non nullable
      print(city.toUpperCase());
    }
  }
  //null-conditional access operator (?.)
  for (var city in cities1){
    print(city?.toUpperCase()); //if city != null call method
  }

  //null-conditional index operator (?[])
  List<int>? numbers = [1, 2, 3]; //list can be null
  numbers = null;
  var item = numbers?[0]; //if numbers is not null, get item by index
  print('item: $item'); //null

  //null-conditional spread operator (...?)
  var numbers2 = [...?numbers];
  print(numbers2);

  //Nullable class properties, methods and objects
  final u1 = User(name: 'Tom');
  //u1.phone = '02';
  assert(u1.phone == null);
  print(u1.phone); //null
  //u1.phone ??= 'no phone';
  print('u1: ${u1.phone?.length ?? 'no phone'}'); //'no phone'

  //late - lazy initialization
  print('id: ${u1.id}'); //id is initializing when you access it

  //null-conditional cascade operator (?..)
  User? u2; //u2 is null
  u2 // ?.. - if u2 not null - modify fields
    ?..name = 'Mike'
    ..phone = '03';
  print('u2: ${u2?.phone?.length.toString()}'); //null

  //Nullable types in functions
  bool? isGood(String? item) {
    if (item == 'good') {
      return true;
    } else if (item == 'bad') {
      return false;
    }
    return null;
  }
  var good = isGood('bad') ?? false;

}

class User {
  User({required this.name}); //constructor
  String name; //not nullable property
  String? phone; //nullable property

  //late - lazy initialization
  //int x = calculate(); //error!!!
  //late - x will be initialized when you access it the first time.
  late int id = calculate();
  int calculate() {
    return name.length + 42;
  }
}

вторник, 6 апреля 2021 г.

Classes

//Dart doesn’t have primitive types!
class _MyClass { //class ("_" - library (file) private)
  var _myProperty = 'default state'; //data member - field
  //_MyClass(); //Default constructor
  void myMethod() { //member function
    print(_myProperty);
  }

  @override
  String toString(){
    return 'MyClass (myProperty: $_myProperty)';
  }
}

class Point {
  int x = 0; //mutable property
  int y = 0; //default value

  Point() : x = 0, y = 0; //def constructor with Initializer list ()
  //Point() : x = 0, y = 0 {} //run before body of the constructor

  Point.def() : this(); //Forwarding constructors

  //named constructor - long form
  Point.set(int x, int y) {
    this.x = x;
    this.y = y;
  }
  //named constructor - short form
  Point.set1(this.x, this.y);
  Point.set2([this.x = 0, this.y = 0]); //optional parameters
  Point.set3({this.x = 0, this.y = 0}); //named parameters

  //old setter method
  bool setter({required int x, required int y}) { //method
    if (x >= 0 && y >= 0) {
      this.x = x;
      this.y = y;
      return true;
    } else {
      return false;
    }
  }

  //old getter method
  String toJson() {
    return '{"x":$x,"y":$y}';
  }

  //new getter - get property
  String get json => '{"x":$x,"y":$y}';

  @override
  String toString() {
    return 'x: $x, y: $y';
  }
}

class Person {
  Person({ //constructor with required named parameters
    required String name,
    required int age,
  }) : assert(name.isNotEmpty), // assert
        assert(age >= 0), // assert
        _name = name, _age = age; //Initializer list for private members

  String _name; //library (file) private
  int _age; //library (file) private

  //factory constructor - can be const, named and unnamed
  factory Person.fromJson(Map<String, Object> json) {
    final pName = json['name'] as String;
    final pAge = json['age'] as int;
    return Person(name: pName, age: pAge);
  }

  @override
  String toString() {
    return 'My name is $_name. I\'m $_age years old.';
  }
}

//Const constructor and immutable class
class Complex {
  const Complex(this.re, this.im); //compile time const
  final double re; //immutable property
  final double im; //- can only be constructed and get but not set!
}

//Named constructor
class Temperature1 {
  Temperature1.celsius(this.celsius);
  Temperature1.farenheit(double farenheit) : celsius = (farenheit - 32) / 1.8;
  double celsius;
}

//Getters and setters
class Temperature2 {
  //constructors
  Temperature2.celsius(this.celsius);
  Temperature2.farenheit(double farenheit) : celsius = (farenheit - 32) / 1.8;
  //property
  double celsius;
  //get property (or calculated property!)
  double get farenheit => celsius * 1.8 +32; //computed member
  //set property
  set farenheit(double faren) => celsius = (faren - 32) / 1.8;
}

//Static methods and variables
class Strings {
  static var welcome = 'Welcome'; //static variable
  static const signIn = 'Sign In'; //static const

  static String greet(String name) => 'Hi, $name';

  static List<Strings> factoryMethod(){ //Static methods
    return <Strings>[];
  }
}

//Singleton - static variable
class MySingleton1 {
  MySingleton1._constructor(); //private named constructor
  static final MySingleton1 instance = MySingleton1._constructor();
}

class MySingleton2 {
  MySingleton2._constructor(); //private named constructor
  static final MySingleton2 _instance = MySingleton2._constructor();
  factory MySingleton2() => _instance; //factory constructor
}

void main() {

  //Objects - instances of classes
  final myObject = _MyClass(); //construct object (reference)
  //var myObject = new _MyClass(); //new - optional
  final sameObject = myObject; //reference to the same object
  print(myObject); //toString()

  myObject._myProperty = 'new state'; //change property
  myObject.myMethod(); //call method

  final p0 = Point(); //default constructor
  print('p0 -> $p0');

  final p1 = Point.set(1, 1) //Cascade operator (..)
  ..x = 5
  ..y = 5;
  print('p1 ${p1.toJson()}'); //old getter method
  print('p1 ${p1.json}'); //new get property

  final p2 = Point.set2(3);
  print('p2 -> $p2');
  final p3 = Point.set3(x: 3);
  print('p3 -> $p3');

  final p4 = Point.def(); //named constructor
  if(p4.setter(x: 3, y: 3)) {
    print('p4.x: ${p4.x}, p4.y: ${p4.y}');
  }
  //constructor assert
  final pers = Person(name: 'Tom', age: 42);
  print(pers);
  //factory constructor
  final json = {'name': 'Mike', 'age': 34};
  final pers1 = Person.fromJson(json); //factory constructor
  print(pers1);

  //Const constructor - immutable objects - good perf!!!
  const complex = Complex(1, 2); // compile time const
  print(complex);
  const listCompl = [ // compile time const
    Complex(3, 4),
    Complex(5, 6),
  ];
  print(listCompl);

  //Named constructor
  final temp1 = Temperature1.celsius(30); //named constructor
  final temp2 = Temperature1.farenheit(90); //named constructor

  //Getters and setters
  print(temp1.celsius); //member
  final temp3 = Temperature2.celsius(30);
  print(temp3.farenheit); //getter
  temp3.farenheit = 93; //setter
  print(temp3.farenheit);

  //Static variables and methods
  print(Strings.welcome);
  print(Strings.signIn);
  print(Strings.greet('Tom'));
  var strings = Strings.factoryMethod(); //static method
  print(strings);

  //Singleton - static instance
  final mySingleton1 = MySingleton1.instance; //explicit singleton
  final mySingleton2 = MySingleton2(); //implicit singleton

}

воскресенье, 4 апреля 2021 г.

Closures

//Anonymous functions
void main() {

  //around scope
  var b = 3; // closure can use it

  //Anonymous functions - Closure or Lambda
  Function emptyFn = (){}; //empty function
  Function aFn = (int a) => print(a * b); //void (int) - action
  //void Function(int) aFn = (int a) => print(a * b);
  void nFn(Function aFn) => aFn(5); //function as parameter
  aFn(5); //() - function operator
  nFn(aFn);

  Function nFn1() { return () => print('return function'); };
  (nFn1())(); // call function from function

  final hi = (String name) => 'Hi, $name'; //String (String)
  print(hi('Sam'));

  //Functions as first class objects
  welcome(hi, 'Patric1');
  welcome((String name) => 'Hi, $name', 'Patric2');

  //Function types
  String bon(String name) => 'Bon, $name';
  String hola(String name) => 'Hola, $name';
  welcome1(hi, 'Patric3');
  welcome1(bon, 'Patric4');
  welcome1(hola, 'Patric5');

  //Closures and collections
  const multiplier = 10;
  const list1 = [1, 2, 3];
  // one expression - =>
  final result = list1.map((e) => e * multiplier);
  // more than one expression - {}
  final result1 = list1.map((e) {
    e++;
    return e * multiplier;
  });

  print(result);
  print(result1);

}

//Functions as first class objects
void welcome(String Function(String) greet, String name) {
  print(greet(name) + ', Welcome!');
}

//Function types
typedef Greet = String Function(String);
//or
//typedef String Greet(String name);

void welcome1(Greet greet, String name) {
  print(greet(name) + ', Welcome!');
}

Functions

//function arguments
void fn1(String name, int age) {
  print("My name is $name. I'm $age years old.");
}

//function return value
String fn2(String name, int age) {
  return 'My name is $name. I\'m $age years old.';
}

//optional argument, default value
void fn3(int a, [int b = 0]) {
  print('a: $a, b: $b');
}

//function named arguments, default value
void fn4(int a, {int b = 0}) {
  print('a: $a, b: $b');
}

//function required named arguments
void fn5({required String name, required int age}) {
  print('My name is $name. I\'m $age years old.');
}

//function named arguments, default values
void fn6({String name = '_', int age = 0}) {
  print('My name is $name. I\'m $age years old.');
}

//function Null Safety
void fn7({String? name, int? age}) {
  print('My name is ${name?? '_'} . I\'m ${age?? 0} years old.');
}

double fn8(List<double?>? values) {
  var sum = 0.0;
  if (values != null) {
    for (var value in values) {
      sum += value?? 0.0;
    }
  }
  return sum;
}

//Fat arrow notation (=>)
int fn9(int x, int y){
  return x + y;
}

int fn10(int x, int y) => x + y;

void fn11(int x, int y) => print(x + y);

//Inner functions
void fnOut(){
  print('Out');
  //..
  void fnIn(){
    print('In');
  }
  fnIn();
  fnIn();
}

void main() {

  fn1('Tom', 42);
  print(fn2('Tom', 42));
  fn3(5);
  fn3(5, 5);
  fn4(5);
  fn4(5, b: 3);
  fn5(name: 'Tom', age: 42);
  fn6();
  fn6(name: 'Tom');
  fn6(age: 42);
  fn6(name: 'Tom', age: 42);
  fn7();
  fn7(name: null, age: null);
  print(fn8(null));
  print(fn8([1, null, 3]));
  print(fn9(5, 5));
  print(fn10(5, 5));
  fn11(5, 5);
  fnOut();

}

Loops

import 'package:characters/characters.dart';

void main() {

  //While loop
  var i = 1;
  while (i < 5) { //local scope
    //print(i);
    i++;
  }

  //Do-while loop
  do {
    //print(i);
    i--;
  } while (i > 0);

  //For loop, continue, break
  for (var j = 1; j <= 5; j++) { //local scope
    if (j == 2) {
      continue;
    }
    print(j);
    if (j == 4) {
      break;
    }
  }

  //For-in loop - iterate over strings and collections
  for (var rune in 'Hello!'.runes) {
    print(String.fromCharCode(rune)); //convert the code point
  }

  for (var char in 'text'.characters) {
    print(char);
  }

  for (var item in [1, 2, 3]) { //List collection
    print(item);
  }

  //For-each loop - forEach() method
  'Dart'.characters.forEach((element) {print(element);}); //closure
  [1, 2, 3].forEach((element) => print(element)); //closure

}

Randoms

import 'dart:math';

void main() {

  //Dice rolling
  var rolling = 1;
  while (rollingDice() != 6){ //function call
    print('Not a max on rolling $rolling');
    rolling++;
  }
  print('You got a max on rolling ${rolling}!');

}

///Random generation function
int rollingDice({int faces = 6}) { //6 faces by default

  var now = DateTime.now();
  final random = Random(now.millisecondsSinceEpoch); //seed
  //final random = Random();

  final result = random.nextInt(faces) + 1;
  print('Your result is $result');
  return result;

}

суббота, 3 апреля 2021 г.

Switchers

var global = 2; //global scope

void main() { //function scope

  //Ternary operator - ?:
  print(5 > 3 ? 'true' : 'false'); // true

  //if-else
  if (global.isEven) { //local scope
    print('even');
  } else if (global.isOdd) {
    print('odd');
  } else {
    print('error');
  }

  //switch (enum, int, String or compile-time constant)
  var pos = Position.first; //enum value
  print(pos.index); //index of enum value

  switch (pos) {
    case Position.first:
      print('gold');
      break;
    case Position.second:
      print('silver');
      break;
    default:
      print('bronze');
  }

}

//enums
enum Position { first, second, third }

Comparisons

void main() {

  //Relations: ==, !=, >=, >, <=, <
  //work with int and double
  var b = 5 > 3; // boolean (bool) type - true or false
  print(5 == 2.0); // false
  print(5 != 2.0); // true

  //Logic: || - OR, && - AND (&& - higher precedence)
  print(5 == 2 || 3 == 3); //true
  print(5 == 5 && 2 > 1); //true

  var txt = 'home';
  print(txt.isNotEmpty && txt.contains('h')); //true

  //Ternary operator - ?:
  print(5 > 3 ? 5 : 3); // 5

  //not-operator (!)
  print(!true); // false

  //String equality
  print('hi' != 'HI'); // true

}

Strings

import 'package:characters/characters.dart'; //use characters library

void main() {

  //There is no Character type
  var char = 'a'; // String

  //String type immutable
  var txt0 = "I'm text.\n"; // String literal can use ""
  var txt1 = 'I\'m text'; // or '' (Dart way)
  print(txt1);
  print(txt1.length);
  print(txt1.codeUnits); // collections of UTF-16 code units
  print(txt1.runes); // Unicode code points - runes
  print(txt1.characters.length); // Unicode grapheme clusters, use characters library

  //Unicode
  print('I \u2764 Dart\u0021'); // hex code for the heart emoji and '!'
  print('I love \u{1F3AF}'); // use {} after FFFF value

  //Concatenation
  txt1 += '!';
  print('[' + txt1 + ']');

  //Interpolation
  print('Hi, $txt1');

  //StringBuffer
  final txt2 = StringBuffer();
  txt2.write('Hello, ');
  txt2.write('Dart!');
  print(txt2.toString());

  //Multi-line (''' or """)
  const txt3 = '''
- line 1
- line 2
- line 3''';
  print(txt3);

  //raw string (r' ' or r" ")
  print(r'C:\temp');

  //Methods
  var str = 'Dart is cool!'.toLowerCase();
  str = str.toUpperCase();
  print(str);
  print(str.contains('IS'));
  print(str.replaceAll('IS', 'IS REALLY'));

}

Packages

Packages

>>dart pub add characters

>>dart pub get 

\pubspec.yaml
============
name: main
description: A simple command-line application.
# version: 1.0.0
# homepage: https://www.example.com

environment:
  sdk: '>=2.12.0 <3.0.0'

dependencies:
#  path: ^1.7.0
  characters: ^1.1.0

dev_dependencies:
  pedantic: ^1.11.0



dart pub -h
Work with packages.

Usage: dart pub [arguments...]
-h, --help          Print this usage information.
    --[no-]trace    Print debugging information when an error occurs.
-v, --verbose       Shortcut for "--verbosity=all".

Available subcommands:
  add         Add a dependency to pubspec.yaml.
  cache       Work with the system cache.
  deps        Print package dependencies.
  downgrade   Downgrade the current package's dependencies to oldest versions.
  get         Get the current package's dependencies.
  global      Work with global packages.
  login       Log into pub.dev.
  logout      Log out of pub.dev.
  outdated    Analyze your dependencies to find which ones can be upgraded.
  publish     Publish the current package to pub.dartlang.org.
  remove      Removes a dependency from the current package.
  upgrade     Upgrade the current package's dependencies to latest versions.
  uploader    Manage uploaders for a package on pub.dartlang.org.

пятница, 2 апреля 2021 г.

Types

void main() {

  //Mutable - Explicit annotation
  dynamic dyn = false; // can be any! type
  num n1 = 1; //num
  n1 = 1.0; // can be int or double
  int i1 = 1; //integer
  double d1 = 1.0; //double
  bool b1 = true; //boolean
  String s1 = 'text'; //String

  //Immutable - Explicit annotation
  const int i2 = 2; // compile time const
  final double d2 = 2.0; // runtime const

  //Inference - Mutable and Immutable
  var i3 = 3; // int
  const d3 = 3.0; // double const
  final s2 = 'UserInput'; // String const

  //Runtime type check - runtimeType, is
  print('${i3.runtimeType} is integer: ${i3 is int}');

  //Conversion
  var d4 = i3.toDouble();
  print(d4.toStringAsFixed(2)); // two decimal places
  var i4 = d4.toInt(); // loss of precision
  print(i4.runtimeType); // int

  //Promotion
  var d5 = i4 * d4; // int * double = double
  var i5 = (i4 * d4).toInt(); // int
  double d6 = 3; // double

  //Down casting - as
  //superclass to subclass, num to int or double
  print((n1 as double).truncate());
  //if promote down casting
  if (n1 is double){
    n1.round();
  }

  //Object type
  Object? o1; // General (super) type for all types
  print(o1.runtimeType); // Null
  //OOP - Inheritance
  o1 = 24; // int
  o1 = 32.0; // double
  o1 = 'text'; // String

}

четверг, 1 апреля 2021 г.

Variables

import 'dart:math'; //use math library

//Comment

///Doc comment
/// # header
/// - list

// main - program start point
void main() {   //function body

  //variable declaration
  var z; //dynamic type
  z = 1; z = 1.0; z = 'one'; //don’t do that

  //all is Object - no primitive types!
  Object? v = null; //can be null

  //Subclassing from Object -> num -> int or double
  //Methods: round, truncate, toInt, toDouble, parse
  print('10.isEven: ${10.isEven}'); //print expression

  //type inference when assigning value
  var w = 1; //int - 1 is integer, 1.0 is double, ...

  //Type-safe - static typing
  w = 5; //type int can store only integers

  //statement with expression x = 5 / 2
  // ~/ - truncating division operator
  var x = 5 / 2; //decimal number 2.5 by default
  print('5 / 2 = $x'); //print variable

  //call a function from math library
  var y = sin(45 * pi / 180); //min, max, sqrt, sin, cos

  //Immutability: Const -> final -> var
  const PI = 3.14; //compile time constant
  final t = DateTime.now().hour; //runtime constant

  //arithmetic operators
  var c = 0;
  c = c + 1; // +, -, *, /, ~/, %
  c += 1; // +=, -=, *=, /=, ~/=, %=
  c++; //c++, c--, ++c, --c
  print(c);

}

Hello, Dart!

Dart SDK 

>>dart create hello

( >>dart create --template console-full hello )

>>cd hello

bin\hello.dart
=========
void main() {
  print('Hello, Dart!');
}

>>dart run 

>>dart run --enable-asserts

>>dart compile exe ./bin/hello.dart

 

dart -h
A command-line utility for Dart development.

Usage: dart [<vm-flags>] <command|dart-file> [<arguments>]

Global options:
-h, --help                 Print this usage information.
-v, --verbose              Show additional command output.
    --version              Print the Dart SDK version.
    --enable-analytics     Enable anonymous analytics.
    --disable-analytics    Disable anonymous analytics.

Available commands:
  analyze   Analyze the project's Dart code.
  compile   Compile Dart to various formats.
  create    Create a new project.
  fix       Apply automated fixes to Dart source code.
  format    Idiomatically format Dart source code.
  migrate   Perform a null safety migration on a project or package.
  pub       Work with packages.
  run       Run a Dart program.
  test      Run tests in this package.

 

dart create -h
Create a new project.

Usage: dart create [arguments] <directory>
-h, --help        Print this usage information.
-t, --template    The project template to use.
                  [console-simple (default), console-full, package-simple, web-simple]
    --[no-]pub    Whether to run 'pub get' after the project has been created.
                  (defaults to on)
    --force       Force project generation, even if the target directory already exists.

Available templates:
  console-simple: A simple command-line application. (default)
    console-full: A command-line application sample.
  package-simple: A starting point for Dart libraries or applications.
      web-simple: A web app that uses only core Dart libraries.


dart compile -h
Compile Dart to various formats.

Usage: dart compile <subcommand> [arguments]
-h, --help    Print this usage information.

Available subcommands:
  aot-snapshot   Compile Dart to an AOT snapshot.
  exe            Compile Dart to a self-contained executable.
  jit-snapshot   Compile Dart to a JIT snapshot.
  js             Compile Dart to JavaScript.
  kernel         Compile Dart to a kernel snapshot.