Dart

Личный сайт Go-разработчика из Казани

Dart is a single threaded, general purpose programming language. It borrows a lot from other mainstream languages. It supports Streams, Futures(known as Promises in JavaScript), Generics, First-class functions(closures) and static type checking. Dart can run in any platform such as Web, CLI, Desktop, Mobile and IoT devices.

Dart’s most controversial feature is its Optional Typing Static Type safety and Sound Type checks.

1import "dart:collection"; 2import "dart:math" as math; 3 4/// Welcome to Learn Dart in 15 minutes. http://dart.dev/ 5/// This is an executable tutorial. You can run it with Dart or on 6/// the Try Dart! site if you copy/paste it there. http://dartpad.dev/ 7/// You can also run Flutter in DartPad by click the `< > New Pad ` and choose Flutter 8 9 10/// In Dart, Everything is an Object. 11/// Every declaration of an object is an instance of Null and 12/// Null is also an object. 13 14 15/// 3 Types of comments in dart 16// Single line comment 17/** 18* Multi-line comment 19* Can comment several lines 20*/ 21/// Code doc comment 22/// It uses markdown syntax to generate code docs when making an API. 23/// Code doc comment is the recommended choice when documenting your APIs, classes and methods. 24 25/// 4 types of variable declaration. 26/// Constants are variables that are immutable cannot be change or altered. 27/// `const` in dart should practice SCREAMING_SNAKE_CASE name declaration. 28const CONSTANT_VALUE = "I CANNOT CHANGE"; 29CONSTANT_VALUE = "DID I?"; //Error 30/// Final is another variable declaration that cannot be change once it has been instantiated. Commonly used in classes and functions 31/// `final` can be declared in pascalCase. 32final finalValue = "value cannot be changed once instantiated"; 33finalValue = "Seems not"; //Error 34 35/// `var` is another variable declaration that is mutable and can change its value. Dart will infer types and will not change its data type 36var mutableValue = "Variable string"; 37mutableValue = "this is valid"; 38mutableValue = false; // Error. 39 40/// `dynamic` is another variable declaration in which the type is not evaluated by the dart static type checking. 41/// It can change its value and data type. 42/// Some dartisans uses dynamic cautiously as it cannot keep track of its data type. so use it at your own risk 43dynamic dynamicValue = "I'm a string"; 44dynamicValue = false; // false 45 46 47/// Functions can be declared in a global space 48/// Function declaration and method declaration look the same. Function 49/// declarations can be nested. The declaration takes the form of 50/// name() {} or name() => singleLineExpression; 51/// The fat arrow function declaration can be an implicit or 52/// explicit return for the result of the expression. 53/// Dart will execute a function called `main()` anywhere in the dart project. 54/// 55example1() { 56 nested1() { 57 nested2() => print("Example1 nested 1 nested 2"); 58 nested2(); 59 } 60 61 nested1(); 62} 63 64/// Anonymous functions don't include a name 65example2() { 66 //// Explicit return type. 67 nested1(void Function() fn) { 68 fn(); 69 } 70 nested1(() => print("Example2 nested 1")); 71} 72 73/// When a function parameter is declared, the declaration can include the 74/// number of parameters the function takes by explicitly specifying the names of the 75/// parameters it takes. 76example3() { 77 planA(fn(String informSomething)) { 78 fn("Example3 plan A"); 79 } 80 planB(fn) { 81 // Or don't declare number of parameters. 82 fn("Example3 plan B"); 83 } 84 85 planA((s) => print(s)); 86 planB((s) => print(s)); 87} 88 89/// Functions have closure access to outer variables. 90/// Dart will infer types when the variable has a value of something. 91/// In this example dart knows that this variable is a String. 92var example4Something = "Example4 nested 1"; 93example4() { 94 nested1(fn(informSomething)) { 95 fn(example4Something); 96 } 97 98 nested1((s) => print(s)); 99} 100 101/// Class declaration with a sayIt method, which also has closure access 102/// to the outer variable as though it were a function as seen before. 103var example5method = "Example5 sayIt"; 104 105class Example5Class { 106 sayIt() { 107 print(example5method); 108 } 109} 110 111example5() { 112 /// Create an anonymous instance of the Example5Class and call the sayIt 113 /// method on it. 114 /// the `new` keyword is optional in Dart. 115 new Example5Class().sayIt(); 116} 117 118/// Class declaration takes the form of class name { [classBody] }. 119/// Where classBody can include instance methods and variables, but also 120/// class methods and variables. 121class Example6Class { 122 var instanceVariable = "Example6 instance variable"; 123 sayIt() { 124 print(instanceVariable); 125 } 126} 127 128example6() { 129 Example6Class().sayIt(); 130} 131 132/// Class methods and variables are declared with "static" terms. 133class Example7Class { 134 static var classVariable = "Example7 class variable"; 135 static sayItFromClass() { 136 print(classVariable); 137 } 138 139 sayItFromInstance() { 140 print(classVariable); 141 } 142} 143 144example7() { 145 Example7Class.sayItFromClass(); 146 new Example7Class().sayItFromInstance(); 147} 148 149/// Dart supports Generics. 150/// Generics refers to the technique of writing the code for a class 151/// without specifying the data type(s) that the class works on. 152/// Source: https://stackoverflow.com/questions/4560890/what-are-generics-in-c 153 154/// Type `T` refers to any type that has been instantiated 155/// you can call whatever you want 156/// Programmers uses the convention in the following 157/// T - Type(used for class and primitype types) 158/// E - Element(used for List, Set, or Iterable) 159/// K,V - Key Value(used for Map) 160class GenericExample<T>{ 161 void printType(){ 162 print("$T"); 163 } 164 // methods can also have generics 165 genericMethod<M>(){ 166 print("class:$T, method: $M"); 167 } 168} 169 170 171/// List are similar to arrays but list is a child of Iterable<E> 172/// Therefore Maps, List, LinkedList are all child of Iterable<E> to be able to loop using the keyword `for` 173/// Important things to remember: 174/// () - Iterable<E> 175/// [] - List<E> 176/// {} - Map<K,V> 177 178 179/// List are great, but there's a restriction for what List can be 180/// outside of function/method bodies. List on the outer scope of class 181/// or outside of class have to be constant. Strings and numbers are constant 182/// by default. But arrays and maps are not. They can be made constant by 183/// declaring them "const". Kind of similar to JavaScript's Object.freeze() 184const example8List = ["Example8 const array"]; 185const example8Map = {"someKey": "Example8 const map"}; 186/// Declare List or Maps as Objects. 187 List<String> explicitList = new List<String>.empty(); 188 Map<String,dynamic> explicitMaps = new Map<String,dynamic>(); 189 190example8() { 191 explicitList.add("SomeArray"); 192 print(example8Map["someKey"]); 193 print(explicitList[0]); 194 195 /// Assigning a list from one variable to another will not be the same result. 196 /// Because dart is pass-reference-by-value. 197 /// So when you assign an existing list to a new variable. 198 /// Instead of List, it becomes an Iterable 199 var iterableExplicitList = explicitList; 200 print(iterableExplicitList); // ("SomeArray"); "[]" becomes "()" 201 var newExplicitLists = explicitList.toList(); // Converts Iterable<E> to List<E> 202} 203 204/// Loops in Dart take the form of standard for () {} or while () {} loops, 205/// slightly more modern for (.. in ..) {}, or functional callbacks with many 206/// supported features, starting with forEach,map and where. 207var example9Array = const ["a", "b"]; 208example9() { 209 for (int i = 0; i < example9Array.length; i++) { 210 print("Example9 for loop '${example9Array[i]}'"); 211 } 212 var i = 0; 213 while (i < example9Array.length) { 214 print("Example9 while loop '${example9Array[i]}'"); 215 i++; 216 } 217 for (final e in example9Array) { 218 print("Example9 for-in loop '${e}'"); 219 } 220 221 example9Array.forEach((e) => print("Example9 forEach loop '${e}'")); 222 223} 224 225/// To loop over the characters of a string or to extract a substring. 226var example10String = "ab"; 227example10() { 228 for (var i = 0; i < example10String.length; i++) { 229 print("Example10 String character loop '${example10String[i]}'"); 230 } 231 for (var i = 0; i < example10String.length; i++) { 232 print("Example10 substring loop '${example10String.substring(i, i + 1)}'"); 233 } 234} 235 236/// `int`, `double` and `num` are the three supported number formats. 237/// `num` can be either `int` or `double`. 238/// `int` and `double` are children of type `num` 239example11() { 240 var i = 1 + 320, d = 3.2 + 0.01; 241 final num myFinalNumDouble = 2.2; 242 final num myFinalNumInt = 2; 243 final int myFinalInt = 1; 244 final double myFinalDouble = 0.1; 245 num myNumDouble = 2.2; 246 num myNumInt = 2; 247 int myInt = 1; 248 double myDouble = 0; // Dart will add decimal prefix, becomes 0.0; 249 myNumDouble = myFinalInt; // valid 250 myNumDouble = myFinalDouble; // valid 251 myNumDouble = myFinalNumInt; // valid 252 253 myInt = myNumDouble; // error 254 myInt = myFinalDouble; // error 255 myInt = myFinalNumInt; // error (implicit downcasts removed in Dart 2.9) 256 myInt = myFinalNumInt as int; // valid 257 258 myDouble = myFinalInt; // error 259 myDouble = myFinalNumInt; // error 260 myDouble = myFinalNumDouble; // error (implicit downcasts removed in Dart 2.9) 261 myDouble = myFinalNumDouble as double; // valid 262 263 print("Example11 int ${i}"); 264 print("Example11 double ${d}"); 265 266} 267 268/// DateTime provides date/time arithmetic. 269example12() { 270 var now = new DateTime.now(); 271 print("Example12 now '${now}'"); 272 now = now.add(new Duration(days: 1)); 273 print("Example12 tomorrow '${now}'"); 274} 275 276/// Regular expressions are supported. 277example13() { 278 var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$"); 279 match(s) { 280 if (re.hasMatch(s)) { 281 print("Example13 regexp matches '${s}'"); 282 } else { 283 print("Example13 regexp doesn't match '${s}'"); 284 } 285 } 286 287 match(s1); 288 match(s2); 289} 290 291/// Boolean expressions support implicit conversions and dynamic type 292example14() { 293 var a = true; 294 if (a) { 295 print("true, a is $a"); 296 } 297 a = false; 298 if (a) { 299 print("true, a is $a"); 300 } else { 301 print("false, a is $a"); /// runs here 302 } 303 304 /// dynamic typed null can not be convert to bool 305 var b; /// b is dynamic type 306 b = "abc"; 307 try { 308 if (b) { 309 print("true, b is $b"); 310 } else { 311 print("false, b is $b"); 312 } 313 } catch (e) { 314 print("error, b is $b"); /// this could be run but got error 315 } 316 b = null; 317 if (b) { /// Failed assertion: boolean expression must not be null) 318 print("true, b is $b"); 319 } else { 320 print("false, b is $b"); 321 } 322 323 /// statically typed null can not be convert to bool 324 var c = "abc"; 325 c = null; 326 /// compilation failed 327 /// if (c) { 328 /// print("true, c is $c"); 329 /// } else { 330 /// print("false, c is $c"); 331 /// } 332} 333 334/// try/catch/finally and throw are used for exception handling. 335/// throw takes any object as parameter; 336example15() { 337 try { 338 try { 339 throw "Some unexpected error."; 340 } catch (e) { 341 print("Example15 an exception: '${e}'"); 342 throw e; /// Re-throw 343 } 344 } catch (e) { 345 print("Example15 catch exception being re-thrown: '${e}'"); 346 } finally { 347 print("Example15 Still run finally"); 348 } 349} 350 351/// To be efficient when creating a long string dynamically, use 352/// StringBuffer. Or you could join a string array. 353example16() { 354 var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e; 355 for (e in a) { 356 sb.write(e); 357 } 358 print("Example16 dynamic string created with " 359 "StringBuffer '${sb.toString()}'"); 360 print("Example16 join string array '${a.join()}'"); 361} 362 363/// Strings can be concatenated by just having string List next to 364/// one another with no further operator needed. 365 366example17() { 367 print("Example17 " 368 "concatenate " 369 "strings " 370 "just like that"); 371} 372 373/// Strings have single-quote or double-quote for delimiters with no 374/// actual difference between the two. The given flexibility can be good 375/// to avoid the need to escape content that matches the delimiter being 376/// used. For example, double-quotes of HTML attributes if the string 377/// contains HTML content. 378example18() { 379 print('Example18 <a href="etc">' 380 "Don't can't I'm Etc" 381 '</a>'); 382} 383 384/// Strings with triple single-quotes or triple double-quotes span 385/// multiple lines and include line delimiters. 386example19() { 387 print('''Example19 <a href="etc"> 388Example19 Don't can't I'm Etc 389Example19 </a>'''); 390} 391 392/// Strings have the nice interpolation feature with the $ character. 393/// With $ { [expression] }, the return of the expression is interpolated. 394/// $ followed by a variable name interpolates the content of that variable. 395/// $ can be escaped like so \$ to just add it to the string instead. 396example20() { 397 var s1 = "'\${s}'", s2 = "'\$s'"; 398 print("Example20 \$ interpolation ${s1} or $s2 works."); 399} 400 401/// Optional types allow for the annotation of APIs and come to the aid of 402/// IDEs so the IDEs can better refactor, auto-complete and check for 403/// errors. So far we haven't declared any types and the programs have 404/// worked just fine. In fact, types are disregarded during runtime. 405/// Types can even be wrong and the program will still be given the 406/// benefit of the doubt and be run as though the types didn't matter. 407/// There's a runtime parameter that checks for type errors which is 408/// the checked mode, which is said to be useful during development time, 409/// but which is also slower because of the extra checking and is thus 410/// avoided during deployment runtime. 411class Example21 { 412 List<String> _names = []; 413 Example21() { 414 _names = ["a", "b"]; 415 } 416 List<String> get names => _names; 417 set names(List<String> list) { 418 _names = list; 419 } 420 421 int get length => _names.length; 422 void add(String name) { 423 _names.add(name); 424 } 425} 426 427void example21() { 428 Example21 o = new Example21(); 429 o.add("c"); 430 print("Example21 names '${o.names}' and length '${o.length}'"); 431 o.names = ["d", "e"]; 432 print("Example21 names '${o.names}' and length '${o.length}'"); 433} 434 435/// Class inheritance takes the form of class name extends AnotherClassName {}. 436class Example22A { 437 var _name = "Some Name!"; 438 get name => _name; 439} 440 441class Example22B extends Example22A {} 442 443example22() { 444 var o = new Example22B(); 445 print("Example22 class inheritance '${o.name}'"); 446} 447 448/// Class mixin is also available, and takes the form of 449/// class name extends SomeClass with AnotherClassName {}. 450/// It's necessary to extend some class to be able to mixin another one. 451/// The template class of mixin cannot at the moment have a constructor. 452/// Mixin is mostly used to share methods with distant classes, so the 453/// single inheritance doesn't get in the way of reusable code. 454/// Mixins follow the "with" statement during the class declaration. 455class Example23A {} 456 457/// Since Dart 3 the 'mixin' keyword is required instead of 'class'. 458mixin Example23Utils { 459 addTwo(n1, n2) { 460 return n1 + n2; 461 } 462} 463 464class Example23B extends Example23A with Example23Utils { 465 addThree(n1, n2, n3) { 466 return addTwo(n1, n2) + n3; 467 } 468} 469 470example23() { 471 var o = new Example23B(), r1 = o.addThree(1, 2, 3), r2 = o.addTwo(1, 2); 472 print("Example23 addThree(1, 2, 3) results in '${r1}'"); 473 print("Example23 addTwo(1, 2) results in '${r2}'"); 474} 475 476/// The Class constructor method uses the same name of the class and 477/// takes the form of SomeClass() : super() {}, where the ": super()" 478/// part is optional and it's used to delegate constant parameters to the 479/// super-parent's constructor. 480class Example24A { 481 var _value; 482 Example24A({value = "someValue"}) { 483 _value = value; 484 } 485 get value => _value; 486} 487 488class Example24B extends Example24A { 489 Example24B({value = "someOtherValue"}) : super(value: value); 490} 491 492example24() { 493 var o1 = new Example24B(), o2 = new Example24B(value: "evenMore"); 494 print("Example24 calling super during constructor '${o1.value}'"); 495 print("Example24 calling super during constructor '${o2.value}'"); 496} 497 498/// There's a shortcut to set constructor parameters in case of simpler classes. 499/// Just use the this.parameterName prefix and it will set the parameter on 500/// an instance variable of same name. 501class Example25 { 502 var value, anotherValue; 503 Example25({this.value, this.anotherValue}); 504} 505 506example25() { 507 var o = new Example25(value: "a", anotherValue: "b"); 508 print("Example25 shortcut for constructor '${o.value}' and " 509 "'${o.anotherValue}'"); 510} 511 512/// Named parameters are available when declared between {}. 513/// Parameter order can be optional when declared between {}. 514/// Parameters can be made optional when declared between []. 515example26() { 516 var _name, _surname, _email; 517 setConfig1({name, surname}) { 518 _name = name; 519 _surname = surname; 520 } 521 522 setConfig2(name, [surname, email]) { 523 _name = name; 524 _surname = surname; 525 _email = email; 526 } 527 528 setConfig1(surname: "Doe", name: "John"); 529 print("Example26 name '${_name}', surname '${_surname}', " 530 "email '${_email}'"); 531 setConfig2("Mary", "Jane"); 532 print("Example26 name '${_name}', surname '${_surname}', " 533 "email '${_email}'"); 534} 535 536/// Variables declared with final can only be set once. 537/// In case of classes, final instance variables can be set via constant 538/// constructor parameter. 539class Example27 { 540 final color1, color2; 541 /// A little flexibility to set final instance variables with syntax 542 /// that follows the : 543 Example27({this.color1, color2}) : color2 = color2; 544} 545 546example27() { 547 final color = "orange", o = new Example27(color1: "lilac", color2: "white"); 548 print("Example27 color is '${color}'"); 549 print("Example27 color is '${o.color1}' and '${o.color2}'"); 550} 551 552/// To import a library, use import "libraryPath" or if it's a core library, 553/// import "dart:libraryName". There's also the "pub" package management with 554/// its own convention of import "package:packageName". 555/// See import "dart:collection"; at the top. Imports must come before 556/// other code declarations. IterableBase comes from dart:collection. 557class Example28 extends IterableBase { 558 var names; 559 Example28() { 560 names = ["a", "b"]; 561 } 562 get iterator => names.iterator; 563} 564 565example28() { 566 var o = new Example28(); 567 o.forEach((name) => print("Example28 '${name}'")); 568} 569 570/// For control flow we have: 571/// * standard switch with must break statements 572/// * if-else if-else and ternary ..?..:.. operator 573/// * closures and anonymous functions 574/// * break, continue and return statements 575example29() { 576 var v = true ? 30 : 60; 577 switch (v) { 578 case 30: 579 print("Example29 switch statement"); 580 break; 581 } 582 if (v < 30) { 583 } else if (v > 30) { 584 } else { 585 print("Example29 if-else statement"); 586 } 587 callItForMe(fn()) { 588 return fn(); 589 } 590 591 rand() { 592 v = new math.Random().nextInt(50); 593 return v; 594 } 595 596 while (true) { 597 print("Example29 callItForMe(rand) '${callItForMe(rand)}'"); 598 if (v != 30) { 599 break; 600 } else { 601 continue; 602 } 603 /// Never gets here. 604 } 605} 606 607/// Parse int, convert double to int, or just keep int when dividing numbers 608/// by using the ~/ operation. Let's play a guess game too. 609example30() { 610 var gn, 611 tooHigh = false, 612 n, 613 n2 = (2.0).toInt(), 614 top = int.parse("123") ~/ n2, 615 bottom = 0; 616 top = top ~/ 6; 617 gn = new math.Random().nextInt(top + 1); /// +1 because nextInt top is exclusive 618 print("Example30 Guess a number between 0 and ${top}"); 619 guessNumber(i) { 620 if (n == gn) { 621 print("Example30 Guessed right! The number is ${gn}"); 622 } else { 623 tooHigh = n > gn; 624 print("Example30 Number ${n} is too " 625 "${tooHigh ? 'high' : 'low'}. Try again"); 626 } 627 return n == gn; 628 } 629 630 n = (top - bottom) ~/ 2; 631 while (!guessNumber(n)) { 632 if (tooHigh) { 633 top = n - 1; 634 } else { 635 bottom = n + 1; 636 } 637 n = bottom + ((top - bottom) ~/ 2); 638 } 639} 640 641/// Optional Positional Parameter: 642/// parameter will be disclosed with square bracket [ ] & square bracketed parameter are optional. 643example31() { 644 findVolume31(int length, int breath, [int? height]) { 645 print('length = $length, breath = $breath, height = $height'); 646 } 647 648 findVolume31(10,20,30); //valid 649 findVolume31(10,20); //also valid 650} 651 652/// Optional Named Parameter: 653/// parameter will be disclosed with curly bracket { } 654/// curly bracketed parameter are optional. 655/// have to use parameter name to assign a value which separated with colan : 656/// in curly bracketed parameter order does not matter 657/// these type parameter help us to avoid confusion while passing value for a function which has many parameter. 658example32() { 659 findVolume32(int length, int breath, {int? height}) { 660 print('length = $length, breath = $breath, height = $height'); 661 } 662 663 findVolume32(10,20,height:30);//valid & we can see the parameter name is mentioned here. 664 findVolume32(10,20);//also valid 665} 666 667/// Optional Default Parameter: 668/// same like optional named parameter in addition we can assign default value for this parameter. 669/// which means no value is passed this default value will be taken. 670example33() { 671 findVolume33(int length, int breath, {int height=10}) { 672 print('length = $length, breath = $breath, height = $height'); 673 } 674 675 findVolume33(10,20,height:30);//valid 676 findVolume33(10,20);//valid 677} 678 679/// Dart has also added feature such as Null aware operators 680var isBool = true; 681var hasString = isBool ?? "default String"; 682 683/// Programs have only one entry point in the main function. 684/// Nothing is expected to be executed on the outer scope before a program 685/// starts running with what's in its main function. 686/// This helps with faster loading and even lazily loading of just what 687/// the program needs to startup with. 688main() { 689 print("Learn Dart in 15 minutes!"); 690 [ 691 example1, example2, example3, example4, example5, 692 example6, example7, example8, example9, example10, 693 example11, example12, example13, example14, example15, 694 example16, example17, example18, example19, example20, 695 example21, example22, example23, example24, example25, 696 example26, example27, example28, example29, 697 example30 // Adding this comment stops the dart formatter from putting all items on a new line 698 ].forEach((ef) => ef()); 699}

Further Reading

Dart has a comprehensive web-site. It covers API reference, tutorials, articles and more, including a useful DartPad (a cloud-based Dart coding playground). https://dart.dev/ https://dartpad.dev/