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

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend