busy developer s guide to dart
play

Busy Developer's Guide to Dart Ted Neward Neward & Associates - PowerPoint PPT Presentation

Busy Developer's Guide to Dart Ted Neward Neward & Associates http://www.tedneward.com | ted@tedneward.com Dart Overview In a nutshell... Dart Overview Dart "Dart is a class-based, single-inheritance, pure object-oriented


  1. Primitive Types Enumerations (enums) – use "enum" keyword; integer-backing – access the integer backing value using ".index" – get a full list of the enum values using static "values" constant – when used in switch statements, compiler checks for full- range evaluation

  2. Primitive Types dynamic – "placeholder" type designed to allow for optional typing essentially compiler will do no type-checking around a dynamic-declaration

  3. Control Flow Ifs, ands, whiles and fors

  4. Control Flow If/else – standard C-style "if" construct else is optional, else if chains tests, etc – must be boolean test expression

  5. Control Flow If if (isRaining()) { print("Welcome to Seattle"); } else if (isSnowing()) { print("Welcome to... uh... the US"); } else { print("Welcome to Las Vegas"); }

  6. Control Flow While and do/while – standard C-style "loop until false" constructs – must be boolean test expression

  7. Control Flow While and do/while while (isRaining()) { print("Stay indoors"); } do { print("Writing code while I stay indoors"); } while(isRaining());

  8. Control Flow For (three-expression style) – pretty much everything the C-style for does

  9. Control Flow For-in (iteration style) – any Iterable object supports for-in – any change to the collection breaks the iteration – Iterable objects also support forEach() (preferred)

  10. Control Flow Switch/case – standard C-style "switch" block – each non-empty "case" must terminate with "break" • empty case statements fall through • alternatively, use "continue {label}" to force fall-through – case matches must be compile-time constants

  11. Control Flow Assert – accept boolean condition, then generate exception if false – only operate as intended in checked mode in production mode, they turn into a no-op

  12. Control Flow Try/catch/throw – "throw new {object}" immediately begins walk up call stack any arbitrary object may be thrown – "try" { body } establishes range of guarded code – "on {type} { body }" executes body on {type} exceptions – "catch(ex) { body }" is the catch-all handler – "finally { body }" always executes

  13. Operators Doing 'x' to 'a' and 'b'

  14. Operators Dart supports full range of operators – mathematical ( ++ -- + - * / % ~/ ) including math-assignment ( = += -= *= /= %= ~/= ) ~/ ~/= are "divide with integer result" – bitwise ( << >> & ^ | ) including bitwise-assign ( <<= >>= ^= |= &= ) – relational ( == != && || <= >= < > ) including conditional ( t : a ? b ) – type-test ( as is is! ) – object-related ( () [] . ?. .. ) – NOTE: operator implementation resolution use the left- hand operand ex: aVector + aPoint will use aVector's implementation of +

  15. Operators Equality tests – == != do an equality comparison meaning, compare the contents – == returns null if lhs or rhs is null – to do an identity comparison, use the identical() function

  16. Operators Null-safe operators – ?? is the null-test operator a ?? b returns a if a != null, else b – ?. is the null-safe resolution operator a?.b yields b returns b if a != null, else null

  17. Functions Capturing logic

  18. Functions Functions: named blocks of code – C-style syntactic approach return-type function-name(param-type param-name, ...) { body } – types are encouraged, but not mandatory function-name(param-name, ...) { body } – body can be elided if it is a simple expression-return function-name(param-name, ...) => expression

  19. Functions Simple functions void printNumber(num number, num times) { print('The number you passed is $number.'); } void printAnotherNumber(number) => print('Here is $number.'); void main() { var printIt = (number) => print('Yet again, $number.'); printNumber(27); printAnotherNumber(27); printIt(27); }

  20. Functions Parameters come in two flavors: required and optional – required come first – optional parameters can be either positional or named (not both) • named defined using {}-denoted enclosing parameter list • positional defined using []-denoted parameter list • optional named parameters invoked using name: value lists

  21. Functions Optional parameters can have default values attached – use "=" syntax after param-name in list – without default value, optional parameters (if not passed) are null

  22. Functions Optional named and positional parameters void doSomething({bool printIt: false, bool logIt: true}) { if (printIt) { print("We're printing something"); } if (logIt) { print("We're logging something"); } } void logIt(String msg, [String language: 'English']) { print("We're logging $msg in $language."); } void main() { doSomething(printIt: true, logIt: false); logIt("Hello, world!"); }

  23. Functions Functions are first-class objects – passed as parameters, stored as variables, etc all functions are of type "function" – "ordinary" objects can also be made callable implement a call() function in the class – Function types can be expressed using "typedef" typedef int Compare(Object a, Object b); "Compare" is now a function type that can be used/compared/etc

  24. Functions First-class functions bool shortName(string name) => name.length < 10; bool printName(string name) { print("$name is easy to vote for."); } void main(List<string> args) { List<string> candidates = [ "Barack Obama", "Joe Biden", "John McCain", "Sarah Palin", "Mickey Mouse", "Goofy" ]; var shortList = candidates.where(shortName); shortList.forEach(printName); }

  25. Functions Functions can be lexically nested – nested functions are no different than non-nested functions – except that they cannot be seen from outside lexical scope in other words, just as with any other variable – aids in implementation-hiding

  26. Functions Anonymous functions (lambdas, closures, etc) – uses "fat arrow" syntax (param-list) => { statements }; (param-list) => statement; – types may be specified to parameter list (optional) – access to surrounding lexical scope – closure capture is by-value, not by-reference value of the variable enclosed is captured at time of closure creation

  27. Functions Closures // "function" is the return type, not a keyword! function makeAdder(num addBy) { // Not seen outside of makeAdder() adder(num i) { return addBy + i; } return adder; } void main() { var addBy2 = makeAdder(2); assert(add2(3) == 5); var addBy4 = makeAdder(4); assert(add4(3) == 7); // Closures capture by-value not by-reference var callbacks = []; for (var i = 0; i < 2; i++) { callbacks.add(() => print(i)); } callbacks.forEach((c) => c()); // prints 0, 1; in JavaScript, this would be 2, 2 }

  28. Classes Defining types in Dart

  29. Classes Classes define types – all objects are instances of a class – class keyword begins definition – classes have members • variables • constructors • methods (including getters/setters) • operators – members can also be static • variables • methods

  30. Classes Class syntax – access is either public or private • denoted by presence/absence of leading _ • "foo" would be public • "_foo" would be private – "this" keyword refers to instance – "." is access operator to obtain members

  31. Classes Cascade operator ("..") – used to reference a previous object – essentially another way of doing "fluent chaining" typically useful for setters or non-return-capturing methods – cascade as many times as desired/necessary

  32. Classes Instance variables – "{type} {identifier}" defines instance variable – implicitly defines getter and setter setter only for mutable (non-final, non-const) variables – initialized to null if not explicitly initialized

  33. Classes Simple class declaration/use class Person { // These are all public String lastName = "(None)"; String firstName; // initially null // These are private (_-prefixed) num _age = 0; Person(this.firstName, this.lastName); Person.singular(String firstName) { this.firstName = firstName; } } void speakers() { Person speaker = new Person("Ted", "Neward"); Person theDude = new Person.singular("The Dude"); speaker.firstName = "The Dude"; }

  34. Classes Constructors – blocks of code to initialize objects before use – no return type, uses same name as class – if no constructor is declared, default (no-arg) constructor is synthesized – "simple constructors" are constructors that just assign params to member variables • use "this.{member}" in parameter list to match params to members • these assignments happen before the body of the constructor runs

  35. Classes Chaining constructors class Point { num x; num y; Point(this.x, this.y); // Chained constructor Point.alongXAxis(num x) : this(x, 0); }

  36. Classes Named constructors – "named constructors" provide additional constructors or clarity "{Classname}.{identifier}(param-list) { body }" – used exactly the same way from client code – syntactically similar (identical) to static methods in other languages

  37. Classes Initializer lists – defined between constructor parameter list and actual body – serves to allow easy member initialization from parameters – initializer lists execute prior to constructor body very handy for initializing final-declared members

  38. Classes Factories are constructors of a sort – they return instances of the type but not always new instances – always invoked using "new" in other words, client never knows the difference

  39. Classes Factories class OverdoneDemo { final String name; static final OverdoneDemo _instance = new OverdoneDemo._internal("Singleton!"); OverdoneDemo._internal(this.name); factory OverdoneDemo() { return _instance; } } void overdone() { var od = new OverdoneDemo(); print(od.name); print(new OverdoneDemo().name); print(new OverdoneDemo().name); }

  40. Classes Methods – functions defined on the class – can be either instance or static • instance have lexical access to "this" by default • static have lexical access to static members by default – can be abstract by leaving out method body (terminate with semicolon) non-abstract classes can have abstract methods

  41. Classes Properties ("getters and setters") – each instance variable already has an implicit getter/setter – use "get"/"set" to implement additional Properties typically these will use "shortcut" function/method syntax

  42. Classes Properties class Rectangle { num left; num top; num width; num height; Rectangle(this.left, this.top, this.width, this.height); num get right => left + width; set right(num value) => left = value - width; num get bottom => top + bottom; set bottom(num value) => top = value - height; }

  43. Classes Operator overriding – finite/limited set of operators available for overriding < > <= >= + - / ~/ * % | ^ & << >> [] []= ~ == – define a non-static method using "operator (op)" as the name – Dart leaves it up to the developer to make common-sense decisions here

  44. Classes Operators class Vector { final int x; final int y; const Vector(this.x, this.y); Vector operator +(Vector v) { return new Vector(x + v.x, y + v.y); } Vector operator -(Vector v) { return new Vector(x - v.x, y - v.y); } } main() { final v = new Vector(2, 3); final w = new Vector(2, 3); assert((v+w).x == 4 && (v+w).y == 6); }

  45. Inheritance Implementation reuse via inheritance

  46. Inheritance Implementation inheritance – single base – use "extends" to denote superclass – use "super" to refere to superclass – instance methods, getters, setters are overridable prefer use of @override to allow compiler verification – note Object.noSuchMethod() this is invoked whenever a member is not found during invocation

  47. Inheritance Interfaces class TV { void turnOn() { _illuminateDisplay(); _activateIRSensor(); } } class SmartTV extends TV { @override void turnOn() { super.turnOn(); _bootNetworkInterface(); _initializeMemory(); _upgradeApps(); } }

  48. Inheritance Interfaces – every class implicitly defines its own interface – classes can "implements" a class and get the interface but no implementation – all members are defined by the interface but not always visible to subclasses

  49. Inheritance Interfaces class ThoughtLeader { String _name; // part of the interface, but not always visible ThoughtLeader(this._name); // not part of the interface String greet(who) => "Hello, $who. I am $_name, a Thought Leader."; } class Imposter implements ThoughtLeader { final _name = ""; // required -- part of the interface String greet(who) => "Hello, $who. Don't you know who I am?"; }

  50. Inheritance Mixins – permit code reuse from classes without establishing IS-A relationship – to implement a mixin, create a class that... • extends Object • declares no constructors • has no class to super

  51. Inheritance Mixins abstract class Musical { bool canPlayPiano = false; bool canCompose = false; bool canConduct = false; void entertainMe() { if (canPlayPiano) { print("playig piano"); } else if (canConduct) { print("waving hands"); } else { print("humming"); } } } class Musician extends Object with Musical { } class Maestro extends Person with Musical, Aggressive, Demented { Maestro(String maestroName) { super.singular(maestroName); canConduct = true; } }

  52. Generics Your favorite reusable quote here

  53. Generics Dart supports parametric polymorphism – aka "templates" or "generics" – type-replacement of type-parameter from defintion-time restrict type parameter via "extends" clause in declaration – angle-bracketed notation (a la Java, C++, C#, etc) – reified types type-parameter accessible at runtime (even in production mode)

  54. Generics Collection literals can be type-parameterized – place the type-parameter in angle-brackets before the actual literal – this will define the types explicitly in otherwise-implicit scenarios

  55. Generics Collection literals void main() { var bowlingLeague = <String>["Walter", "Donny", "The Dude"]; var bowlingScores = <String, int>{ "Walter":'198', "Donny":'196', "The Dude":'217' }; var names = new List<String>(); // same as bowlingLeague var scores = new Map<String,int>(); // bowlingScores var uniqueNames = new Set<String>.from(bowlingLeage); print(uniqueNames is Set<String>); // true }

  56. Generics Generic functions – methods/functions can have type parameters as well – place angle-bracketed type-parameter list immediately after name

  57. Asynchrony Walking and chewing gum at the same time (in Dart)

  58. Asynchrony Async/await – Dart supports asychrony through async/await keywords and Future and Stream objects – for-in can be used with Stream objects prefix the "for" with "await"

  59. Metadata Providing data about types in Dart

  60. Metadata Dart supports metadata through annotations – @-prefixed class instances – accessible via reflection – custom annotation types possible simple class

  61. Libraries Using/creating reusable bodies of code in Dart

  62. Libraries Libraries are APIs and a unit of privacy – every Dart app is a library – libraries can be distributed using "pub" (package manager)

  63. Libraries Import – import specifies how a namespace from one library is used in the scope of another library "import 'dart:html'" – argument to import is a URI specifying the library • "dart:" is a special scheme for Dart built-in libraries • "package:" scheme refers to package manager-managed libraries • otherwise, a file system path – imports can define a prefix for all names in the library "import 'package:lib2/lib2.dart' as lib2;" – selectively import symbols using "show" "import 'package:foo/hello.dart' show foo;" – selectively exclude symbols using "hide" "import 'package:foo/hello.dart' hide foo;"

  64. Libraries Deferred import – libraries can be lazily loaded (deferred) until required – import using "deferred as" "import 'package:deferred/hello.dart' deferred as hello;" – then load-on-demand using loadLibrary() this returns a Future

  65. Libraries Creating libraries – libraries consist of multiple things • code units • manifest (pubspec.yaml) – Dart has strong recommendations about file organization "strong" meaning "some are requirements"

  66. Libraries Library organization – root directory contains pubspec.yaml (manifest) – root directory contains "lib" • by convention, exported code lives in "lib" • by convention, implementation code lives in "lib/src" – root will often have other directories • example • test • tool (library-private-use tools) • bin (public-use tools)

  67. Libraries pubspec.yaml – text file (YAML format) describing the library – name: (required) – version: (required for pub.dartlang.org) – description: (required for pub.dartlang.org) – author or authors: (optional) – homepage: (optional) – documentation: (optional)

  68. Libraries pubspec.yaml – dependencies: – dev_dependencies: – dependency_overrides: used to override dependencies – environment: configure version of Dart SDK used – executables: puts package executables on the path – transformers: configures code transformers

Recommend


More recommend