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();
}
вторник, 27 апреля 2021 г.
Composite
воскресенье, 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
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
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
>>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
//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 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.