0% found this document useful (0 votes)
1K views97 pages

Language Tour - Dart PDF

Uploaded by

John K Samuel
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF or read online on Scribd
0% found this document useful (0 votes)
1K views97 pages

Language Tour - Dart PDF

Uploaded by

John K Samuel
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF or read online on Scribd
A Tour of the Dart Language This page shows you how to use each major Dart feature, from variables and operators to classes and libraries, with the assumption that you already know how to program in another language. To learn more about Dar's core libraries, ee A Tour ofthe Dart Libraries (/guidesylibraries/library-tour) Note: You can play with most ofthese features using DartPad (/tools/dartpad). Consult the Dart Language Specification /guides/language/spec) whenever you want more details about a language feature. A basic Dart program The fllowing code uses many of Darts most basic features: U1 define a function. printNunber(num aNunber) { print (‘The number is SaNumber y 5 // Print to console. U1 This is where the opp starts executing pain() { var nunber = 42; // Declare and initialize a variable. printNumber (number); // Calta function. y open Drtpad Here's what this programuses that apps oar almost al Da 3p 11 This « coment. Use//t indicate thal there of theline sa comment. leat se. "For dtl se Comments, Atpe. ome of te otherbltin types ae Sing it and boo a ‘Anumber literal, Number literals are a kind of compile-time constant print() handy way to display output, ) “(or Astring literal $SvariabLeNane (or ${expression}) String interpolation: including a variable or expression’s string equivalent inside of a string literal. For more information, see Strings. rain() The special, required, top-level function where app execution starts, Far more information, see The main\) function, Away to declare a variable without specifying its type. Note: Our code follows the conventions in the Dart style guide (/guides/language/effective-dart/styl). For example, we use two- space indentation, Important concepts As you learn about the Dart language, Keep these facts and concepts in mind: Everything you can place ina variable’ an object, and every objects an instance of a class. Even numbers, functions, and null are objects, All objects inherit from the Object™ clas. Specifying static types (such as num in the preceding example) clarifies your intent and enables static checking by tools, (You ‘might notice when you're debugging your code that variables with no specified type get a special type: dynamic.) Specifying static types is optional in Dart 1.x, however Dart is moving towards being 2 fully type safe language, Instrong mode (/guides/language/sound-dart, static and runtime checks ensure that your code is type safe, helping you catch bugs in development, rather than at runtime. Strong mode is optional in Dart 1.x, but nat optional in Dart 2.0 (/dart-2.0). Dart parses all your code before runningit. You can provide tips to Dart—for example, by using types or compile-time constants— [Link] errors or help your code run faster, Dart supports top-Ievel functions (such as main()), as well as functions tied toa class or objec (staticand instance methods, respectively). You can also create functions within functions (nested or local functions Similarly, Dart supports top-level variables, as well as variables tied toa class or objec (static and instance variables). Instance variables are sometimes known as fields or properties Unlike Java, Dart doesn't have the keywords public, protected, and private. If an identifier starts with an underscore (), it's private to its library. For details, see Libraries and visibility Identifierscan start mith a letter or, followed by any combination of those characters plus digi ‘Sometimes it matters whether something_is an expression ora statement, o we'll precise about those two words. Dart tools can report two kinds of problems: warnings and errors. Warnings are just indications that your code might not work, but they don’t prevent your program from executing. Errors can be either compile-time or run-time. A compile-time error prevents the code from executing at all, run-time error results in an exception being raised while the code executes. Dart [Link] two runtime modes: production and checked. We recommend that you develop and debug in checked mode, and deploy to production mode. Productian modes the default runtime mode of 2 Dart program, optimized for speed. Production ‘mode ignores assert statements and static types. Checked modeis a developer-friendly made that helps you catch some type errors during runtime. For example, ifyou assign 2 non-number toa variable declared as a nun, then checked mode throws an exception Dart 2.0 note: Checked mode won't be in Dart 2.0, For more information, see Dart 2.0 Updates. (/dart-2.0} Keywords The following table lsts the words that the Dart language treats specially. abstract? assert async? asynct? await? break catch class const continue covariant» éefault deferred do dynamic? else export! external? extends factory false final finally for eet? it implements? import? Ubrary? ll operator! part rethrow return set? static! super switch sync*? this throw tue wy typedef! void while with yield? yield? Words withthe superscript are built-in identifiers, Avoid using built-in identifiers as identifier. A compile-time error happensi you try touse a built-in identifier for a class or type name. 2 Words withthe superscript2 are never, limited reserved words related to asynchrony support added after Darts 1.0 release, You can’t use async, axait, or yield as an identifier in any function body marked with asyne, async, or sync, For more information, see synchrony support. Allother words in the keyword table are reserved words. You can't use reserved words as identifiers. Variables Here's an example of creating a variable and assigning value to it var name = “Bob*; Variables are references. The variable called nane contains a reference toa String object with 2 value of “Bob”, Default value Uninitialized variables have an initial value of nuld. Even variables with numeric types are intially null, because numbers are objects int Linecount; assert(lineCount == null); U1 Variables (even if they wiLl be numbers) are initially null Note: The assert() cals ignored in production mode. In checked mode, assert(condition) throws an exception unless conditionis true, For details, see the Assert section. Dart 2.0 note: Checked mode won't be in Dart 2.0, For more information, see Dart 2.0 Updates. (/dart-2.0] Optional types Dart 2.0 note: Types won't be optional in Dart 2.0, but you'l still be able to omit some type annotations, thanks to type inference, For more information, see Dart 2.0 Updates. /dart-2.0) You have the option of adding static types to your variable declarations: String name *aob's [Adding typesis a way to clearly express your intent. Tools such as compilers and editors can use these types te help you, by providing code completion and early warnings for bugs and code completion. Note: Ths page follows the style guide recommendation /guides/language/effective-dart/designstype-annotations) of using var, rather than type annotations, for local variables. Even under strong mode (/dart-7.0), you can specify var—the analyzer infers the type where possible. Final and const Ifyou never intend to change a variable, use final or const, ether instead of var orn addition toa type. A final variable can be set only ‘once; a const variable is a compile-time constant. (Const variables are implicitly final. A final top-level or clas variable is initialized the first time it’s used, Note: instance variables can be Final but not con: Here's an example of creating and setting a final variable: final name = "Bob"; // Or: final String name = 'Bob'; // name = ‘Alice’; // Unconmenting this causes an error Use const for variables that you want to be compile-time constants. Ifthe const variable is atthe class level, markt static const. Where you declare the variable, set the value to a compile-time constant such as a number or string literal const variable, or the result of an arithmetic operation on constant numbers: 10200005 // Unit of pressure (dynes/em2) 1.01325 * bar; // Standard atmosphere The const keyword isn't just for declaring constant variables. You can also use it to create constant values, as well as to declare constructors that create constant values. Any variable can have a constant value. // Note: [] creates an empty List. V1 const [] creates an enpty, immutable List (EIA) var foo = const []; // foo is currently an EIA. final bar = const []; // bar will always be an ETA. const baz = const []; // baz is a compile-time constant EIA // You con change the value of @ non-final, non-const variable, U/ even if it used to have a const value. foo = [3 // You con't change the value of a final or const variable. U1 bar = [1]; // Unhandled exception. U1 baz = []; // Unhandled exception. For more information on using const to create constant values, see Lists, Maps, and Classes. Built-in types ‘The Dart language has special support for the following types: + numbers + strings + booleans + lists also known as arrays) + maps + runes (for expressing Unicode characters ina string) + symbols You can initialize an object of any of these special types using aliteral. Forexample, ‘this 4s a string! isa string literal, and trues boolean literal Because every variable in Dart refers to an object—an instance ofa class—you can usually use constructorsto initialize variables. Some of the builtin types have their own constructors. For example, you can use the Map() constructor to create a map, using code such as ew *ap(). Numbers Dart numbers come in two flavors: int Integer values, which generally should be in the range-2"*to 2" double” 64-bit (dovble-precision) floating-point numbers, as specified by the IEEE 754 standard Both int and double are subtypes of nus.” The num type includes basic operators such as ,-,/, and *, and is also where you'll find abs(), ceil(), and #loo-(), among other methods. (Bitwise operators, such as>>, are defined in the int class.) ifnum and its subtypes don't have what you're looking for, the dart:math™ library might: Integers outside ofthe -2* to 2° range currently behave dferently in JavaScript produced from Dart cade than they ‘do when the same Dart code runsin the Dart VM. The reason is that Dart is specified to have arbitrary-precision integers, but JavaScript isn't, See issue 1533" for detail Integers are numbers without a decimal point, Here are some examples of defining integer literals: var hex = OXDEADBEEF; var bigint = 34653465624652437659238076592374958739845729; la number includes a decimal, tis a double. Here are some examples of defining double literals: var y = 1.15 var exponents = 1.42¢5; Here's how you turn a stringinto a number, or vice versa UW String -> int var one = [Link](‘1"); assert(one == 1); U1 String -> double var onePointone = [Link]("2.1"); assert(onePointone == 1.1); UL it -> string String onefsstring = [Link](); assert(oneasstring == '1'); // double -> string String piAsstring = [Link](2) 5 assert(piasstring == '3.14"); The int type specifies the traditional bitwise shift (<<, >), AND (8), and OR ()) operators. For example: assert((3 << 1) == 6); // 081 << 1m» 0110 assert((3 >> 1) == 3); // 0012 >> 1 == 0901 assert((3 | 4) == 7); // 0012 | 6100 == 0112 Literal numbers are compile-time constants. Many arithmetic expressions are also compile-time constants, as long as their operands, are compile-time constants that evaluate to numbers. const msPersecond = 1608; const secondsuntilretry = 5; const msUntilRetry = secondsun Retry * msPerSecond; Strings [Dart strings a sequence of UTF-16 code units. You can use either single or double quotes to create a string var si = ‘Single quotes work well for string Literals."; var s2 = "Double quotes work just as well"; var 53 = "It\'s easy to escape the string delimiter’; var 54 = "It's even easier to use the other deliniter."s You can put the value of an expression inside a string by using ${expression). Ifthe expression is an identi let, you can skip the To get the string corresponding to an abject, Dat calls the object’s tostring() method. aamaos? Language Te [Ome var s = ‘string interpolation’; assert(‘Dart has $5, which is very handy Dart has string interpol which is very handy.") assert(‘That deserves all caps. * + "${[Link]()} 1s very handy!" == “That deserves all caps. ° + STRING INTERPOLATION {s very handy!*); Note: The code units erator tests whether two objects are equivalent. Two strings are equivalent if they contain the same sequence of You can concatenate strings using agjacent string literals or the + operator: var si = ‘String * ‘concatenation’ works even over Line breaks." “string concatenation works even over “Line oreaks."); assert(st var s2 = "The + operator + ‘works, as well.*; “The + operator works, as well.*); assert(s2 Another way to create a multi-line string: use a triple quote with either single or double quotation marks: var st = You can create multi-line strings like this one. var s2 = """This is also a multi-line string You can create raw’ string by prefxing it with r var s = r"In a raw string, even \n isn’t special."; ‘See Runes for detals on how to express Unicode characters ina string Literal strings are compile-time constants, as long as any interpolated expression is @ compile-time constant that evaluates to null ora numeric, string, or boolean valve. // These work in a const string. const aconstNun = @; ‘trues const aConststring = 'a constant string’; const aConstBool U1 These do NOT work in a const string. var aNun = 2: var aBool = true; var aSteing = ‘a string’; const aConstList = const [1, 2, 3]; const validConststring ‘SaConstNun $aConstBool $aconststring’ // const invalidconststring = '$aNum $abool $astring $oConstlist’; aamaos? Language Te [Ome For mote information on using strings, see Strings and regular expressions (/guideslibraries/library-tourdstrings-and-regular- expressions). Booleans To represent boolean values, Dart has a type named bool. Only two objects have type book: the boolean literals true and false, which are both compile-time constants. When Dart expects a boolean value, only the value trues treated as true, Allother values are treated as false, Unlike in JavaScript, values such as 1, "astring", and soneObject are all treated as alse For example, consicer the following code, which is valid both as JavaScript and as Dart code: var name = “Bob"; if (name) { U7 Prints in Javascript, not in bart. print("You have a nane!"); y you run this code as JavaScript, it prints "You have a name!” because name isa non-null object. However, in Dart running in production mode, the preceding code doesn’t print at all because nane is converted to False (becausenane I= true).In Dart running in checked mode, the preceding code throws an exception because the nare variable is not a bool, Dart 2.0 note: Checked mode won't be in Dart 2.0, For more information, see Dart 2.0 Updates. (/dart-2.0) Here's another example of code that behaves diferently in JavaScript and Dart a) print (‘2S prints p else { print(‘bart in production node prints this line."); 71 However, in checked mode, if (1) throws an U1 exception because 1 is not boolean. y iis Line."); Note: The previous two samples work only in production mode, not checked mode. In checked mode, an exception Is thrown if rnon-boolean is used when a boolean value is expected, Dart’s treatment of booleans is designed to avoid the strange behaviors that can arise when many values can be treated as true. What this means for you is that, instead of using code like if (nonbooLeanvaLue), you should instead explicitly check for values. For example: U1 Check for an empty string. var fullNane = °° assert([Link]); U1 Check for zero. var nitPoints = @; assert(hitPoints <= 0); U Check for null. assert(unicorn = null); U1 Check for NaN. var iMeantToooThis = 0 / 8; assert(iMeant [Link]); Lists Perhaps the most common collection in nearly every programming language isthe array, or ordered group of objects. In Dart, arrays are List objects, so we usually just cal them lists Dart lst literals look ike JavaScript aray literals. Here's a simple Dart ist: var list = [1, 2, 3]; Note: f you're wondering whether this list literal is strong mode compliant (/guides/language/sound-dar) itis. Thanks to type inference (/guides/language/sound-dartétype-inference), the analyzer infers that List has type Listcint>. Ifyou try to add non integer objects to this list under strong mode, the analyzer raises an error. Lists use zero-based indexing, where 0's the index ofthe frst element and list. length - 1istheindex ofthe last element. You can getalist’s length and refer to ist elements just as you would in JavaScript var list = [1, 2, 3]; assert([Link] == 3); assert(List[1] == 2); List(a} = 15 assert(list[1] == 1); To create alist that’s a compile-time constant, add const before the list literal: var constantList = const [1, 2, 313 UH constantlist[1] = 1; // Uncommenting this causes an error, The Listtype has many handy methods for manipulating lists. For more information about lists, see Generics and Collections (guides/librariesylibrary-tourtcollections) Maps In general, a map s an object that associates keys and values, Both keys and values can be any type of object. Each key occurs only ‘once, but you can use the same value multiple times. Dart support for maps is provided by map literals and the Map" type. Here are a couple of simple Dart maps, created using map literals: var gifts = ¢ W keys values “finst! : "partridge’, second": “turtledoves’, fifth’ : ‘golden rings h var nobleGases V/ Keys Values 2: ‘heliue’, 38: ‘neon’, 38: ‘argon’, % Note: f you're wondering whether these map literals are strong mode compliant (/guides/languageysound-dart), they are. “Thanks to type inference /guides/language/sound-dartétype-inference), the analyzer infers that gifts, for example, has the type MapeString, String>. Ifyou try to add non-string objects to this map under strong mode, the analyzer raises an error. You can cteate the same objects using a Map constructor var gifts = new ap(); gifts[‘First'] = ‘partridge’; Bifts[ second] = ‘turtledoves" gifts[‘Fifth’] = “golden rings var noblecases = new Map(); nobleGases{2] = *heliun’; nobleGases[18] = ‘neon; nobleGases[18] = ‘argon’; ‘Add a new key-value pair to an existing map just as you would in JavaScript: var gifts = (first': partridge’); gifts['fourth"] = ‘calling birds’; // Add a key-value pair Retrieve a value from a map the same way you would in JavaScript var gift (Cfirst!: ‘partridge’ }s assert(gifts| first") == ‘partridge'); you look fora key that isn't in a map, you get a null in retue: var gifts = (*Finst': ‘partrédge’)s assert(gifts[ "fifth'] =» null); Use . Length to get the number of key-value pairs in the map: var gifts = (*first': ‘partrédge’); gifts[‘fourth*] = ‘calling birds"; assert(gifts. length == 2); To create a map that’s a compile-time constant, add const before the map literal: final constantiap = const { 2: ‘heliun’, 28: ‘neon’, 18: ‘argon’, % U/ constontMap[2} = ‘Helium’; // Unconmenting this causes an error. For more information about maps, see Generics and Maps (/uides/libraries/lbrary-tourtmaps). Runes In Dart, runes are the UTF-32 code points ofa string, Unicode defines a unique numeric value for each letter, digit, and symbol used in all ofthe world’s writing systems, Because a Dart stringis a sequence of UTF-16 code units, expressing 22-bit Unicode values within a string requires special syntax The usual way to express a Unicode code pointis \u0x, where 00K isa 4-digt hexidecimal value. For example, the heart character (¥) 's\u2665. To specify more or less than 4 hex digits, place the value in curly brackets. For example, the laughing emoji ("is \u(1#60@). The String class has several properties you can use to extract rune information. The codeUnitat and codeUnit properties return 16. bit code units. Use the runes property to get the runes of astring. The following example illustrates the relationship between runes, 16-bit code units, and 32-bit code points. Click the run button (3) tose runes inaction. Note: Be careful when manipulating runes using list operations. This approach can easily break down, depending on the particular language, character set, and operation. For more information, see How do | reverse a String in Dart? on Stack. Overflow. symbols ‘A Symbol object represents an operator or identifier deciared in a Dart program. You might never need to use symbols, but they're invaluable for APIs that refer to identifiers by name, because minification changes identifier names but not identifier symbols. To get the symbol for an identifier, use a symbol tral, whichis just # fellowed by the identifier radix oar ‘Symbol literals are compile-time constants For more information on symbols, see dartsmirrors- reflection /guides/ibraries/library-tour#éartmitro Functions Dartisa true object-oriented language, so even functions are objects and have a type, Function. This means that functions can be assigned to variables or passed as arguments to other functions. You can also call an instance ofa Dart cass aif it were a function. For details, see Callable classes. Here's an example of implementing 2 function: bool isNoble(int atomictunber) { return _nobleGases[atomicNunber] y Although Effective Dart recommends type annotations for public APIs (/guides/language/effective-dart/design#do-type-annotate publi-apis), the function still works lf you omit the types: AsNoble(atonicnumber) { return _nobleGases[atomicNunber] I= null; y For functions that contain ust one expression, you can use a shorthand syntax: bool isNoble(int atomictunber) _pobleGases[atomicNunber] != null; The=> expr syntaxis shorthand for { return expr; }.The-=> notation is sometimes referred to as fat arrow syntax. Note: Only an expression-not a statement-can appear between the arrow (->) and the semicolon (;), For example, you can’t put anif statement there, but you can use a conditional expression. {function can have two types of parameters: required and optional. The required parameters are listed first, followed by any optional parameters Optional parameters Optional parameters can be either positional or named, but not both Optional named parameters ‘When calling a function, you can specify named parameters using paramWame: value. For example: enableFlags(bold: true, hidden: false); When defining a function, use (paran2, paran2, .) to specify named parameters: //1 Sets the [bold] and [hidden] flags to the values U/1 you specify. enableFlags({bool bold, bool hidden}) { uw y Optional positional parameters Wrappinga set of function parameters in] marks them as optional positional parameters String say(String fron, String msg, [String device]) { var result = "$from says $msg’; if (device != null) { result = "$result with a $device'; return result; y Here's an example of calling ths function without the optional parameter: assert(say('Bob’, ‘Houdy’) == "Bod says Howdy"); {and here's an example of calling ths function with the thd parameter: assert(say('Bob', ‘Howdy’, "stoke signal") == "Bob says Howdy with a smoke signal’); Default parameter values ‘Your function can use =to define default values fr both named and positional parameters. The default values must be compile-time constants. fno default value's provided, the default value is null. Here's an example of setting default values for named parameters: aamaos? Language Te [Ome U11 Sets the [bold] ond [hidden] flags to the values you U1 specify, defaulting to false. void enableFlags((bool bold = false, bool hidden = false)) ( uw y // bold will be true; hidden will be false. enableFlags(bold: true); Version note: Old code might use a colon (:) instead of set default values of named parameters. The reason is that before SOK 1.21, only : was supported for named parameters. That supports likely to be deprecated, so we recommend that you use = to specify default values, and specify an SDK version of 1.21 or higher. (/tools/pub/pubspectsdk-constraints) ‘The next example shows how to set default values for positional parameters: String say(String fron, String msg, [String device = ‘carrier pigeon’, String nood]) { var result = "$from says $msg’; 4f (device != null) ¢ result = “$result with 2 $device'; Af (mood I= null) { result = "$result (in a $s0od mood)"; return results » assert(say('Bob", "Houdy") Bob says Howdy with a carrier pigeon"); You can also pass lists or maps as default values. The following example defines a function, dostu¢), that specifies a default list for the List parameter and a default map for he gifts parameter, void dosturf( {Listcints List = const (1, 2, 3), MapcString, String> gifts = const { First’: "paper’, second’: “cotton’, “ehind": "Leather" ») ¢ print(‘List: $list’); print(‘gifts: Sgifts'); y The main() function Every app must have a top-level nain() function, which serves as the entrypoint tothe app. The main() function returns void and has ‘an optional List parameter for arguments. Here's an example of the nain() function for a web app: void main() ( querySelector(“#sample_text_id") ‘ext = “Click me! onClick. Listen(reverseText) ; Note: The ... syntax in the preceding code is called a cascade. With cascades, you can perform multiple operations on the members ofa single object. Here's an example of the main() function for a command-line app that takes arguments: // Run the app Like this: dart [Link] 1 test void main(Listestring> argusents) { print(argunents); assert([Link] == 2); assert(int. parse(argunents[2]) assert(argunents[1] == ‘test'); You can use the args library” to define and parse command-line arguments Functions as first-class objects You can passa function asa parameter to another function. For example printéLenent(elenent) { print(elenent); y var list = [1, 2, 3]; // Pass printéLenent os @ parameter. [Link](printElenent); You can also assign a function to a variable, such as: var loudify = (esg) => ‘111 ${[Link]()} 111"; assert(loudify(‘hello") =="!!! HELLO 111"); This example uses an anonymous function. More about those n the next section. Anonymous functions Most functions are named, such as main() or printElenent(). You can also create a nameless function called an anonymous function, for sometimes a lambda or closure. You might assign an anonymous function to a variable so that, for example, you can add or remove it from a collection, {An anonymous function looks similar to a named function— zero or more parameters, separated by commas and optionally typed, between parentheses Dart 2.0 note: Types won't be optional in Dart 2.0, but you'l still be able to omit some type annotations, thanks to type inference, For more information, see Dart 2.0 Updates, /dart-.0) ‘The code block that follows contains the function's body: (CUype} param, 10) ¢ codestock; h The following example defines an anonymous function with an untyped parameter, The function, invoked foreach item in the list, printsa string that includes the value at the specified index var list = [‘apples', ‘oranges*, ‘grapes’, “bananas’, ‘pluns’]; List foreach(() ( print([Link](i).tostring() +": * + 4) ys Clik then buton (ft execute the code. Ifthe function contains only one statement, you can shorten it using ft arrow notation. Paste the following line into DartPad and click run to verify that itis functionally equivalent. List. foreach((4) print (List-indexOf(1).tostring() +": ‘ + 4))5 Lexical scope Dart sa lexically scoped language, which means that the scope of variables is determined statically, simply by the layout of the code, You can “follow the curly braces outwards" to see fa variable isin scope, Here is an example of nested functions with variables at each scope level var toplevel = true; rain() { var insideMain nyFunction() { var insideFunction = true; nestedFunction() { var insideNestedFunction = true; assert(toplevel); assert(insidetain) ; assert(insideFunction) ; assert(insideNestedFunction); Notice how nestedFunction() can use variables from every level, all the way upto the top level. Lexical closures {A closureis a function object that has access to variables ints lexical scope, even when the function is used outside ofits original scope. Functions can close over variables defined in surrounding scopes. Inthe following example, sakeadder() captures the variable addy. Wherever the returned function goes, it remembers addy. aamaos? Language Te [Ome U1 Returns a function that adds [add8y] to the V1) function's argument. Function nakeAdder(num acdBy) { return (num i) => addBy + i5 y ain() ¢ U/ Create a function that adds 2. var add2 = makeadder(2); U1 Create a function that adds 4. var adda = makeadder(4); assert(add2(3) = assert(adda(3) 3 ns Testing functions for equality Here's an example of testing top-level functions, static methods, and instance methods for equality: foot) (2 // A top-Level. function class A { static void bar() {} // A static method void baz() (} // An instance method y ain() ¢ // Comparing top-tevel functions. 1 Comparing static methods x = [Link]; assert([Link] == x); U1 Comparing instance methods new A(); // Instance #1 of A new A()3 // Instance #2 of A var y = 5 x= wbaz3 U1 These closures refer to the same instance (#2), // 30 they're equal. assert([Link] == x); // These closures refer to different instances, U1 so they're unequal assert([Link] != w.b3z); Return values Allfunctions return a value. fno return value is specified, the statement return nul; is implicitly appended to the function body. Operators Dart defines the operators shown in the following table. You can override many of these operators, as described in Overridable operators. Description unary postfix unary prefix multiplicative additive shite bitwise AND bitwise xOR bitwise OR relational and type test equality logical AND logical oR Operator expres expr-- (0 (] . 2. sexpr expr ~expr expr ~-0 Sy eel @ Operator » conditional expr ? expr: expr3 cascade assignment see kee oe be Me |e 28 When you use operators, you create expressions. Here are some examples of operator expressions: arore aist In the operator table, each operator has higher precedence than the operators inthe rows that follow it. For example, the multiplicative ‘operator x has higher precedence than (and thus executes before) the equality operator =, which has higher precedence than the logical AND operator &&, That precedence means that the following two lines of code execute the same way: U1 2: Parens improve readabiLity. AF ((o % £ == @) AB (6% i == @)) // 2: Harder to read, but equivalent. if (ni == @ a8 d Bi == 0) Warning: For operators that work on two operands, the leftmost operand determines which version of the operatoris used. For ‘example, ifyou have a Vector object and a Point object, Vector + aPoint uses the Vector version of + Arithmetic operators Dart supports the usual arithmetic operators, as shown in the following table, Operator Meaning * Add - subtract “oor Unary minus also known as negation (reverse the sign ofthe expression) : Multiply / Divide ~ Divide, returning an integer result x Get the remainder ofan integer division (rodulo) example assert(2 assert(2 assert(2 assert(5 assert(5 assert(5 % 2 // Result is a double // Result is an integer // Remainder print('s/2 = $(5~/2) © ${582}")5 // 5/2 = 201 Dart also supports both prefix and postfix increment and decrement operators Operator Meaning svar vor = vor + 1 (expression valueis var + 3) vores var = var + 1 (expression valueis var) var var = var ~ 1 (expression valueis var ~ 3) - var = var ~ 2 (expression valueis var) Example var a, bi a= 6; b= Has // Increment a before b gets its value. assert(a == b); //1==1 Hs // Increment @ AFTER b gets its value. assert(a I= b); // 1 I= 8 be // Decrement before b gets its value. assert(a ss b); // to» -1 // Decrement a AFTER b gets its value. assert(a I= b); //-1 l= Equality and relational operators The following table lists the meanings of equality ané relational operators Operator Meaning Equal; see discussion below Not equal > Greaterthan < Lessthan > Greaterthan or equal to < Less than or equalto To test whether two objects x and y represent the same thing, use the == operator Inthe rare case where you need to know whether two objects are the exact same object, use the ident ical ()” function instead.) Here's how the =» operator works: Lifer yis ull, return true if both are null, and false if only one is null er first 2 Return the result ofthe method invocation x.==(y). (That's right, operators such as == are methods that are invoked on ‘operand, You can even override many operators, including ==, as you'l see in Overridable operators} Here's an example of using each of the equality and relational operators: assert(2 == 2) assert(2 I= 3) assert(3 > 2); assert(2 <3); assert(3 assert(2 ecco Larne Tae Oa Type test operators The as, is, and is! operators are handy for checking types at runtime. Operator Meaning as Typecast is ‘True ifthe object has the specified type is! False ifthe object has the specified type The result ofobj is Tis trueif ob; implements the interface specified by 7. For example, obj is Object is always true. Use the as operator to cast an object to a particular type. In general, you should use it as a shorthand for an is test on an object following by an expression using that object. For example, consider the following code; Af (emp is Person) { // Type check [Link] = '30b'; d You can make the code shorter using the as operator: (enp as Person).firstNane = "Bob's Note: The code isn’t equivalent. if exp is null ornota Person, the frst example (with is) does nothing; the second (with as) throws an exception Assignment operators aamaos? Language Te [Ome As you've already seen, you can assign values using the = operator. To assign only ifthe assigned-to variable is null, use the 2?= operator. jalue; // Assign value to a alue; // If b is null, assign value to b; // otherwise, b stays the sane ‘Compound assignment operators such as += combine an operation with an assignment. Here's how compound assignment operators work: Compound assignment Equivalent expression Foran operator op: a op= > a= aop0 Example: aa anasd The following example uses assignment and compound assignment operators: var a // Assign using = ans // Assign and multiply: a assert(a == 6); Logical operators You can invert or combine boolean expressions using the logical operators. Operator Meaning expr inverts the following expression (changes false to true, and vice versa) uN logical oR ry logical AND Here's an example of using the logical operators: AF (Idone 8& (col U1 +0 something. y 0 II col == 3) ¢ Bitwise and shift operators You can manipulate the individual bits of numbers in Dart Usually, you'd use these bitwise and shift operators with integer. Operator Meaning & AND H or * XOR expr nary bitwise complement (0s become 1s; 1s become 0s) « Shift eft » Shift right Here's an example of using bitwise and shift operators: final value = 0x22; final bitnask = exof; assert((value & bitnask) assert((value & ~bitmask) assert((value | bitnask) assert((value * bitmask) assert((value << 4) assert((value >> 4) 7 x28); // AND NOT ex2F)s // OR ex2d); // XoR U1 Shift Left exe2); // Shift right Conditional expressions Dart has two operators that let you concisely evaluate expressions that might otherwise require if-else statements: condition ? exprt : expr2 IF condition’s true, evaluates expr (and returns its value}; otherwise, evaluates and returns the value of expr2. expr 22 expr2 If expr1is non-null, returns its value; otherwise, evaluates and returns the value of expr2, When you need to assign a value based on a boolean expression, consider using ? var finalstatus = m-isinal ? ‘final’ ; ‘not final’; Ifthe boolean expression tests for null, consider using ??. String toString() => msg 2? [Link](); The previous example could have been written at least two other ways, but not as succinctly: U1 Slightly Longer version uses ?: operator. String toString() => msg == null ? [Link]() : msgs // Very Long version uses if-else statement. String tostring() { 4 (msg == mull) { return [Link](); p else { return nse; Cascade notation (..) Cascades (..) allow you to make a sequence of operations on the same object. In addition to function calls, you can also access fields ‘on that same object This often saves you the step of creating a temporary variable and allows you to write more fluid code. Consider the following code: queryselector("#button') // Get an object. sstext = ‘Confirm’ // Use its menbers. = -[Link](" important!) ssonCLick.1isten((e) => window-alert(*Confirmed!*)); The first method call, querySelector(), returns a selector object. The code that follows the cascade notation operates on this selector ‘object, ignoring any subsequent values that might be returned The previous examples equivalent to: var button = querySelector( #button'); [Link] = "Confirm; [Link](" important"); [Link]-1isten((e) => [Link](*Confirmed!")); You can also nest your cascades. For example: inal addressBook = (new AddresstookBuilder() name = ‘jenny’ fenail = ‘jenny@[Link]' phone = (new PhoneNunberBuilder() nunber = ‘415-555-0108 «label = ‘hone") -build()) build); Be careful to construct your cascade on a function that returns an actual object. For example, the following code fails U1 Does not work var sb = new Stringouffer(); [Link]('foo"). .write(‘bar') The [Link]() cll eturns void, and you can’t construct a cascade on vot Note: Strictly speaking, the “double dot” notation for cascades isnot an operator. it's just part ofthe Dart syntax Other operators You've seen most ofthe remaining operators in other examples: Operator Name For more information about the ., Function application List access Member access Conditional member access Represents a function call Refers to the value at the specified indexin thelist Refers toa property of an expression; example: Foo. bar selects property bar from expression foo Like ., but the leftmost operand can be nul; example: Foo? .bar selects property bar from expression oo unless foo s null (in which case the value of foo? bar is null), nd. . operators, see Classes. Control flow statements You can control the flow of your Dart code using any of the following You can also affect the control flow using tr Afandelse for loops whtle and do-white loops break and continue switch and case Ifand else ‘catch and throu, as explained in Exceptions. Dart supports i¢ statements with optional ese statements, as the next sample shows, Also see conditional expressions. Sf (AsRainingQ)) ( you. bringRaincoat(); } else if (isSnowing()) ¢ you,meardacket(); p else { car. putTopbown(); y Remember, unlike JavaScript, Dart treats all values other than true 2s false, See Booleans for more information. For loops You can iterate with the standard for loop, For example: var message = new StringBuffer("Dart is fun"); for (var i= @; i < 55 ist) ( [Link]('!"); y Closures inside of Dar’ For loops capture the value ofthe index, avoiding a common pitfall found in JavaScript, For example, consider: var callbacks = [J; for (var i» 8 i < 25 ise) ( [Link](() => print(i)); y callbacks. forEach((c) => €())5 The outputs @ and then 3, as expected. In contrast, the example would print 2 and then 2in JavaScript. Ifthe object that you are iterating over is an Iterable, you can use the Fortach() method, Using forEach() isa good option if you don’tneed to know the cureent iteration counter: candidates. fortach( (candidate) => candidate. interview()); Iterable classes such as List and Set also support the fer-in form of iteration (/guides/librarieslibrary-tourtiteration}: var collection = (@, 1, 2]5 for (var x in collection) { print(x)s y While and do-while [Awhile loop evaluates the condition before the loop: while (1isbone()) { dosonething(); y ‘[Link] loop evaluates the condition afterthe loop: do { printLine()3 } while (IatendofPage())s Break and continue Use break to stop looping: while (true) ( 4f (shutDownRequested()) break; processinconingRequests(); y Use conti ue to skip to the next loop iteration: for (int 1 = @} 4 < candidates.1 var candidate = candigates[i]; AF ([Link] < 5) ¢ continue; maths Ast) { candidate. interview(); ‘You might write that example differently if you're using an iterable candidates where((c) => [Link] >= 5) -forEach((c) => ¢-interview()); ‘Switch and case ‘Switch statements in Dart compare integer, string, or compile-time constants using. such as alist or set “The compared objects must all be instances of the same class (and not of any ofits subtypes), and the class must not override ~~. Enumerated types work wellin switch statements. Note: Switch statements in Dart are intended for limited circumstances, such asin interpreters or scanners. Each non-empty case clause ends with a break staternent, asa rule. Other valid ways to end a non-empty case clause are a continue, throw, or return statement, Use adefault clause to execute code when no case clause matches: var conmand = "OPEN"; switeh (connand) { case ‘CLOSED": executeClosed(); break; case ‘PENDING’ executePending(); break; case ‘APPROVED" : executeApproved() break; case "DENIED" executeDenied(); break; case ‘OPEN executeopen(); break; default: ‘executeUnknown() The following example omits the break statement in case clause, thus generating an error: var command = “OPEN' 3 switch (connand) { case ‘OPEN ‘executeopen(); // ERROR: Missing break causes an exception! ! case *CLOSED" executeClosed(); break; However, Dart does support empty case clauses, allowing a form of fallthrough: var conmand = “CLOSED switch (command) { case ‘CLOSED: // Empty case falls through ease "NOH_CLOSED" U1 Runs for both CLOSED and NOw_CLOSED. executeliovClosed(); break; you really want fall-through, you can use a continue statement and a label: aamaos? Language Te [Ome var conmand = “CLOSED'; switch (command) { case ‘CLOSED" executeClosed(); continue nowClosed; // Continues executing at the nowClosed Label. nowclosed cease ‘NOM_ CLOSED // Runs for both CLOSED and NOw_CLOSED. ‘executehiowClosed(); break; ‘case clause can have local variables, which are visible only inside the scope ofthat clause. Assert Use an assert statement to disrupt normal execution ifa boolean condition is false, You can find examples of assert statements throughout this tour. Here are some more: // Make sure the variable has a non-null value, assert(text I= null); // Moke sure the value ts Less than 160. assert(nunber < 120); // Make sure this is on https URL. assert([Link](https")); Note: Assert statements work only in checked mode. They have no effect in production mode. Dart 2.0 note: Checked mode won't be in Dart 2.0, For more information, see Dart 2.0 Updates. (/dart-2.0) To attach a message toan assert, adda string as the second argument. assert([Link]( https"), URL (SuriString) should start with "https”."); Version note: The second argument was introduced in SDK 1.22, The first argument to assert can be any expression that resolves to a boolean value or to a function. Ifthe expression’s value or function's return value is true, the assertion succeeds and execution continues. Ifit's false, [Link])is thrown. the assertion fils and an exception (an Exceptions Your Dart cade can throw and catch exceptions. Exceptions are errors indicating that something unexpected happened. Ifthe exception isnt caught, the isolate that raisee the exception is suspended, and typically the isolate and its program are terminated In contrast to Ja all of Dart’ exceptions are unchecked exceptions, Methods do not declare which exceptions they might throw, and you are not required to catch any exceptions. Dart provides Exception ® and Error“ types, as well as numerous predefined subtypes. You can, of course, define your own exceptions. However, Dart programs can throw any non-null object—not just Exception and Error objects—as an exception, Throw Here's an example of throwing, or raising, an exception: ‘throw new FormatException( ‘Expected at least 1 section); You can also throw arbitrary objects: ‘throw ‘Out of Manasl'; Because throwing an exception is an expression, you can throw exceptions in ~> statements, as well as anywhere else that allows expressions: AistanceTo(Point other) => ‘throw new UninplenentedError(); Catch Catching, or capturing, an exception stops the exception from propagating (unless you rethrow the exception}. Catching an exception gives you a chance to handleit: try ( breedMoreLlanas(); } on outofLianaséxception { buyMoreLanas() y Tohhandle code that can throw more than one type of exception, you can specify multiple catch clauses, Te frst catch clause that matches the thrown objects type handles the exception, Ifthe catch clause does not specify a type, that clause can handle any type of thrown abject: try ( breedMorel lanas(); } on OutofLianaséxception { U1 A specific exception buyMoret lanas(); ‘on Exception catch (e) ¢ U1 Anything else thot ts an exception print (‘Unknown exception: $e"); ) catch (e) // No specified type, handles all print('Sonething really unknown: $e"); As the preceding code shows, you can use either on or catch or both. Use on when you need to specify the exception type, Use catch when your exception handler needs the exception object. You can specify one or two parameters to catch(). The firsts the exception that was thrown, and the second isthe stack trace (a StackTrace” object } on Exception catch (e) ¢ print(‘Exception details:\n $e"); } catch (e, 5) ( print(‘Exception details:\n $e"); print(‘Stack trace:\n $s"); > To partially handle an exception, while allowing it to propagate, use the rethrow keyword, aamaos? Language Te [Ome final foo = void misbehave() ( try { foo = “You can't change @ final variable’s value.";, } catch (©) { print(‘misbehave() partially handled ${[Link]} rethrow; // Allow callers to see the exception. y void main() ( try ¢ rnisbehave(); } eaten (0) print(’nain() finished handling ${[Link]) Finally To ensure that some code runs whether or not an exception is thrown, use a finally clause. Ifno catch clause matches the exception, the exception is propagated after the finally clause runs: try ( breedvoreLlanas(); } Finally { U1 Always clean up, even if an exception ts thrown. cleantlanastalls()3 y The finally clause runs after any matching catch clauses: try breedMoreLanas(); } eateh(e) ¢ print(‘Error: $e"); // HandLe the exception first. } finally { cleanLlanastalis(); // Then clean up. y Learn more by reading the Exceptions /guides/libraries/library-tourtexceptions) section, Classes Dart is an object-oriented language with classes and mixin-based inheritance. Every object is an instance ofa class, and all classes descend from Object. Mixin-based inheritance means that although every class (except for Object) has exactly one superclass class body can be reused in multiple class hierarchies, To create an object, ou can use the new keyword with a constructorfor a class. Constructor names can be either CLassName or CLassNome. identifier. For example: var jsonData = [Link]("("x":1, U1 Create a Point using Point() var pi = new Point(2, 2); // Create @ Point using [Link](). var p2 = new [Link])son(jsondata); Objects have members consisting of functions and data (methods and instance variables, respectively), When you calla method, you invokeit on an object: the method has access to that object's functions and date, Use adot(.) to refer to an instance variable or method var p = new Point(2, 2); U1 Set the value of the instance variable y. py // Get the value of y. assert(p.y == 3); // Invoke distanceTo() on p. num distance = [Link](new Point(4, 4)); Use 2. instead of . to avoid an exception when the leftmost operands null: UL Tf p AS non-null, set its y value to 4. pry = 45 ‘Some classes provide constant constructors To create 2 compile-time constant using a constant constructor, use const instead of new: var p = const InmutablePoint(2, 2)3 Constructing two identical compile-time constants results in a single, canonical instance: var a = const InmutablePoint(1, 1); var b = const InqutablePoint(1, 1); assert(identical(a, b)); // They are the same instance! To get an objects type at runtime, you can use Object’s runtineType property, which returns a Type“ object. print("The type of a is $([Link]}"); The following sections discuss how to implement classes. Instance variables Here's how you declare instance variables: class Point ( nun x; // Declare instance variable x, initially null. num y3 // Declare y, initially mult num 2 = @; // Declare z, initially 8. All uninitialized instance variables have the value nul Allinstance variables generate an implicit gettermethod. Non-final instance variables also generate an implicit setter method. For details, see Getters and setters class Point ( num ys y eain() ¢ var point = new Point(); point.x = 43 // Use the setter method for x. assert(point .x assert(point.y y 4); // Use the getter method for x = null); // Values default to nut It you initialize an instance variable where itis declared (instead of ina constructor or method), the value Is set when the instanceis created, wich is before the constructor and its initializer list execute, Constructors Declare a constructor by creating 2 function with the same name as its class (plus, optionally, an additional identifier as described in Named constructors). The most common form of constructor, the generative constructor, creates a new Instance of a class: class Point ( num y3 Point(num x, num y) { // There's a better way to do this, stay tuned. this.x The this keyword refers to the current instance. Note: Use this only when there is a name conflict, Otherwise, Dat style omits the this, ‘The pattern of assigning a constructor argument to an instance variable is so common, Dart has syntactic sugar to make it easy: class Point ( num y; // Syntactic sugar for setting x and y U1 before the constructor body runs. Point(this.x, this.y); y Default constructors Ifyou don’t declare a constructor, a default constructor is provided for you. The default constructor has no arguments and invokes the no-argument constructor in the superclas, Constructors aren't inherited ‘Subclasses don't inherit constructors from their superclass. A subclass that declares no constructors has only the default (no argument, noname} constructor. Named constructors Use a named constructor to implement multiple constructors fora class orto provide extra clarity: class Point ( num y; Point(this.x, this.y); // Named constructor Point. fron3son(Wap json) ( x= Json['x']; y = json['y']s Remember that constructors are not inherited, which means that a superclass’s named constructor isnot inherited by a subclass. Ifyou want a subclass to be created with a named constructor defined inthe superclass, you must implement that constructor in the subclass Invoking a non-default superclass constructor By default, a constructor in a subclass calls the superclass’ unnamed, no-argument constructor, The supeclas's constructors called atthe beginning ofthe constructor body. fan inialize lists also being used, it executes before the superclass called, In summary, the order of executions as follows 1 initilzer ist 2. supercass's no-arg constructor 2 main class's no-arg constructor ifthe superlass doesn'thave an unnamed, no-argument constructor, then you must manually cal one ofthe constructrsin the ‘superclass. Specify the superclass constructor after a colon (:), just before the constructor body (if any). Inthe folowing example, the constructor fr the Employee class calls the named constructor frit superclass, Person, lick the run button (FS) to execute the code Because the arguments tothe superclass constructor are evaluated before invoking the constructor, an argument can be an expression such as a function cal class Employee extends Person ( Employee() : super. frondson( Findbefaultoata()) > Note: When using super() in a constructor’ initialization lis, putt last. or more information, see the Dart usage guide (iguides/language/effective-dart/usagetdo-place-the-super-cal-last-in-a-constructor-initialzationist). Warning: Arguments to the superclass constructor do not have access to this, For example, arguments can call static methods but notinstance methods. Initializer list Besides invoking a superclass constructor, you can also initialize instance variables before the constructor body runs. Separate iniializers with commas. class Point ( num y3 Point(this.x, this.y); // Initialize List sets instance variables before // the constructor body runs: Point .fronson(Map sorMap) jsontapl x"), y = Jsonmap('y") { print("In [Link](): ($x, $¥)")s y hand side ofan initializer does not have access to this, Warning: The righ aamaos? Language Te [Ome Iniializer ists are handy when setting up final felds. The following example initializes three final elds in an initializer list. Click the run button (J) to execute the code. Redirecting constructors Sometimes a constructors only purpose sto redirect to another constructor inthe same clas. A redirecting constructor’ body is empty, with the constructor call appearing ater a colon () aamaos? Language Te [Ome class Point ( num y; // The main constructor for this class. Point(this.x, this.y); U/ delegates to the main constructor. Point alongxAxts(num x) : this(x, 8); Constant constructors your class produces objects that never change, you can make these objects compile-time constants. To do this, define a const constructor and make sure that all instance vatlables are Final, class InnutablePoint { ‘final num x; ‘final nun y: const InnutablePoint(this.x, this.y); static final InnutablePoint origin = ‘const InmutablePoint (2, 2); Factory constructors Use the Factory keyword when implementing a constructor that doesnt always create a new instance ofits class. For example, factory constructor might return an instance from a cache, o it might return an instance ofa subtype ‘The following example demonstrates a factory constructor returning objects from a cache: aamaos? Language Te [Ome class Logger ( final String name; bool mite = false; // cache is Librory-private, thanks to the _ in front U1 of its name static final map _cache = (}; factory Logger(String rane) ( 4f (cache. containskey(nare)) { return _cache( name); } else ¢ Final logger = new Logger._internal (nave); _cache[nare] = logger; Feturn logger; » Logger._internal([Link]); void log(string msg) { af (Imute) { print (ase); y Note: Factory constructors have no access to this, Toinvoke a factory constructor, you use the new keyword: var logger = new Logger( UI"); Logger. 1og( ‘Button clicked"); Methods Methods are functions that provide behavior for an object. Instance methods Instance methods on objects can access instance variables and this, The dist: of an instance method: 1ceT@() method in the following sample is an example import ‘dart:nath’; class Point num y3 Point(this.x, this.y); num distanceTo(Point other) ( var dx = x - other.x; var dy = y - [Link] return sqrt(dx * ax + dy * dy); Getters and setters Getters and setters are special methods that provide read and write access to an object's properties. Recall that each instance variable has an implicit getter, plus a setter if appropriate, You can create additional properties by implementing getters and setters, using the get and set keywords: class Rectangle ( nun left; num top; num widths num heights Rectangle(this. left, [Link], [Link], [Link]); // define two calculated properties: right and bottom. num get right => left + width; set right(num value) => left = value ~ widths num get botto= top + heights set botton(num value) => top = value - heights y rain() ¢ var rect = new Rectangle(3, 4, 20, 15); assert([Link] == 3); [Link] = 12; assert([Link] == -8); > With getters and setters, you can start with instance variables, later wrapping them with methods, all without changing client code, Note: Operators such as increment (++) work in the expected way, whether or not a getter is explicitly defined, To avoid any unexpected side effects, the operator cals the getter exactly once, savingits value ina temporary variable. Abstract methods Instance, getter, and setter methods can be abstract, defining an interface but leaving its implementation up to other classes. To makea method abstract, use a semicolon (}) instead of a method body: abstract class Deer { U1 «Define instance variables and methods. void doSonething(); // Define an abstract method. y class EffectiveDoer extends Doer { void dosonething() { U1 .-Provide an implementation, so the method is not abstract here... Calling an abstract method results in a runtime error Also see Abstract classes. Overridable operators You can override the operators shown inthe fllowing table. For example, fyou define aVectr class, you might define a + method to add two vectors < + a > / . oO ® - - x > Here's an example of a class that overrides the + and - operators: class Vector ( final int x; final int ys const Vector(this.x, this.y); UII overvides + (a +b). Vector operator +(Vector v) { return new Vector(x + v.x, ¥ + V.y) U1 overrides - (a - b). Vector operator -(Vector v) { return new Vector(x - v.x, y - v.y)3 y atn() ¢ final v = new Vector(2, 3); final w = new Vector(2, 2); Uv = (2, 3) assert(v.x == 2 88 vy MUvewes (4, 5) assert((v + m).x = 4 8& (V+ wD. == 5)5 Uv owen (8, 1) assert((v - m).x 22 8 88 (v- w)-y == 1)5 Ityou override ==, you should also override Object’s hashCode getter. For an example of overriin map keys (/guides/libraries/ibrary-tourkimplementing-map-keys) and hashcode, see Implementing For more information on overriding, in general, see Extending a class Abstract classes Use the abstract modifier to define an abstract class—a class that can't be instantiated. Abstract classes are useful fr defining interfaces, often with some implementation. f you want your abstract class to appear to be instantiable, define a factory constructor. Abstract classes often have abstract methods, Here's an example of declaring an abstract class that has an abstract method: U/ This class is declared abstract ond thus // can't be instantiated. abstract class Abstractcontainer { // «define constructors, fields, methods void updatechildren(); // Abstract method. y The following class isn’t abstract, and thus can be instantiated even though it defines an abstract method class Specializedcontainer extends AbstractContainer { // ...befine more constructors, fields, methods... void updatechildren() { // «Implement updatechildren()... // Abstract method causes @ warning but U1 doesn't prevent instantiation. void doSonething(); y Implicit interfaces aamaos? Language Te [Ome Every class implicitly defines an interface containing all the instance members of the class and of any interfaces it implements. Ifyou want to create a class A that supports class B's API without inheriting B's implementation, class A should implement the B interface. ‘Aclass implements one or more interfaces by declaring them in an implements clause and then providing the APIs required by the interfaces. For example: // A person. The implictt interface contains greet(). class Person ( // In the interface, but visible only in this Library. ‘final _nane; // Not in the interface, since this is @ constructor. Person(this._nane); // In the interface. String greet (who) => ‘Hello, $who. I am $nane."; d // An implementation of the Person interface. class Inposter inplenents Person { // We have to define this, but we don't use it. final _nane = ""5 String greet (who) => ‘HL $who. Do you know who T am?*; y greetdob(Person person) => [Link] (“bob"); rain() { print(greetBob(new Person( kathy'))); print(greetBob(new Inposter())); y Here's an example of specifying that a class implements multiple interfaces: class Point inplenents Comparable, Location ( uw y Extending a class Use extends to create a subclass, and super torefer to the superclass: class Television ( void turnon() { _Sluninatepisplay()s Tactivaterrsensor(); uw y class SnartTelevision extends Television ( void turnon() { super. turnon() _pootNetworkinterface()s Tinitializetenory(); Tupgradeapps() 3 uw y Overriding members Subclasses can override instance methods, getters, and setters. You can use the Boveride annotation to indicate that you are intentionally overriding a member: class SnartTelevision extends Television ( Goverride void turnon() { Tonarrow the type of a method parameter or instance variable in code that is type safe (/guides/language/sound-dart), you can use the covariant keyword (/guides/language/sound-problemstthe-covariant-keyword) noSuchMethod() To detec or react whenever code attempts to use 8 non-existent method or instance variable, you can override nosuchMethoa() class A { // Unless you override noSuchMethod, using a // non-existent member results in a NoSuchMethodérror. void noSuchMethod(Iavocation mirror) { print(‘You tried to use a non-existent nenber:’ + ‘$(nieror-menberNane)") Ifyou use nosuchttethnod{) to implement every possible getter, setter, and method for one or more types, then you can use the @proxy annotation to avoid warnings proxy class A { void noSuchMethod(Iavocation mirror) { An alternative to @proxy, if you know the types at compile time, isto just declare that the class implements those types. class A implenents SoneClass, SonetherClass ( void noSuchMethod(Iavocation mirror) { For more information on annotations, see Metadata, Enumerated types Enumerated types, often called enumerations or enums, are a special king of class used to represent a fixed number of constant values. Using enums Declare an enumerated type using the enum keyword: enum Color < red, green, blue y aamaos? Language Te [Ome Each value in an enum has an index getter, which returns the 2ero-based position of the value inthe enum declaration. For example, the first value has index 0, and the second value has index 1. assert([Link]. index assert([Link] assert([Link]. index To get alist ofall of the valuesin the enum, use the enum's values constant. Listccoler> colors = [Link] assert(colors[2] == [Link]); You can use enums in switch statements. fthe ein switch (e) is explicitly typed as an enum, then you're warned if you don't handle all ofthe enum’s values: enun color { red, Breen, blue y Wow Color acolor = [Link]; suiteh (acolor) { case [Link]: print(‘Red as roses!"); break; case Color. green: print(‘Green as grass!"); break; default: // Without this, you see a WARNING. print(aceler); // "[Link]” Enumerated types have the following limits: + You car't subclass, mixin, orimplement an enum, + You can't explicitly instantiate an enum, For more information, see the Dart Language Specification (/guides/language/spec). Adding features to a class: mixins Mins ar a way of using a cas’ codein multiple cass hierarchies To use a mixin, use the with keyword followed by one or more mixin names. The following example shows two classes that use mixins: class Musician extends Performer with Musical ( uw class Maestro extends Person with Musical, Aggressive, Denented { Maestro(String maestroNane) { name = naestroNane; canConduct = true; Toimplement a mixin, create a class that extends Object, declares no constructors, and has no calls to super. For example: abstract class Musical { bool canPlayPiano = false; bool canConpose = false; bool canconduct = false; void entertainte() { Af (canPlayPiano) { print ("Playing piano’); } else iF (canconduct) { print(*waving hands"); } else { print (*Hurming to self") y Note: As of 1.13, two restrictions on mixins have been led from the Dart VM: aamaos? Language Te [Ome + Mixins allow extending from a class other than Object. + Mixins can call super() ‘These “super mixins” are not yet supported in dart2/s and require the --supermixin flag in dartanalyzer. For more information, see the article Mins in Dart, /aticles/language/mixins) Class variables and methods Use the static keyword to implement class-wide variables and methods. Static variables Static variables (class variables) are useful forclass-wide state anc constants: class Color ( static const red const Color(‘red'); // A constant static variable. final string name; // An instance variable. const Color([Link]); // A constant constructor. y rain() { assert([Link] == “red’); y Static variables arent initialized until they're used. Note: This page follows the style guide recommendation /guides/language/effective-dart/stylesidentifiers) of preferring jowerCanel Case for constant names, aamaos? Language Te [Ome Static methods Static methods (class methods) do not operste on an instance, and thus do not have access to this. For example: import ‘dart:nath'; class Point ( num ys Point(this.x, this.y); static num distancesetween(Point a, Point ») var dx = a.x = Bux; var dy = ay - by; return sqrt(dx * dx + dy * dy)s y ain() ¢ var a = new Point(2, 2); var b = new Posnt(4, 4); var distance = [Link](a, b); assert(distance < 2.9 & distance > 2.8); Note: Consider using top-level functions, instead of static methods, for common or widely used utilities and functionality. You can use static methods as compile-time constants, For example, you can passa static method as a parameter toa constant constructor. Generics aamaos? Language Te [Ome Ifyou look at the API documentation for the basic array type, List,“ you'l see thatthe type is actually List. The«<..notation marks Listas a generic (or parameterized) tyoe—a type that has formal type parameters. By convention, type variables have single- leter names, such as, T, 5, K, and Why use generics? Because types are optional in Dart 1.x, you never haveto use generics. You might wantto, though, for the same reason you might want {0 use other types in your code: types (generic or not} let you document and annotate your code, making your intent clearer. Dart 2.0 note: Types won't be optional in Dart2.0, but you'l stil be able to omit some type annotations, thanks to type inference, For more information, see Dart2.0 Updates. (/dart-2.0) For example, ifyou intend fora ist to contain only strings, you can declare itas List (read thatas "lst of string"). That way you, your fellow programmers, and your tools (such as your IDE and the Dart VM in checked mode) can detect that assigning a non- string to the lists probably a mistake. Here's an example: var nanes = new List(); [Link]éAl1(["Seth", ‘Kathy’, ‘Lars']); Mon [Link](42); // Fails in checked mode (succeeds in production mode). Another reason for using generies isto reduce code duplication, Generics let you share a single interface and implementation between many types, while stil taking advantage of checked mode and static analysis early warnings. For example, say you create an interface for caching an object: abstract class Objectcache ( Object getBykey(String key); setsyxey(String key, Object value); y You discover that you want a string-specific version of this interface, so you create another interface: abstract class Stringcache ( String getBykey(string key); setaykey(String key, String value); » Later, you decide you want a number-spacific version of tis interface... You get the idea Generic types can save you the trouble of creating al these interfaces. Instead, you can create a single interface that takes 2 type parameter: abstract class CachecT> { T getBykey(String key); sevsykey(String key, T value); y In this code, Tis the stand-in type. It's a placeholder that you can think of as type that a developer will define later. Using collection literals List and map literals can be parameterized. Parameterized literals are just lke the literals you've already seen, except that you add (fr lists) or (for maps) before the opening bracket. You might use parameterized literals when you want type watnings in checked mode, Heres example of using typed literals: var names = ['Seth*, ‘Kathy’, ‘Lars']; var pages = ( [Link]": “Honepage’,, [Link]’: “Hints for web robots’, [Link]": “Ke are people, not machines” b Using parameterized types with constructors To specify one or more types when using a constructor, put the types in angle brackets (c..>) just after the class name. For example: var nanes = new List(); [Link](["Seth', ‘Kathy’, ‘Lars']); var naneSet = new Set.fron(nanes); The following code creates a map that has integer keys and values of type View: var views, new Mapcint, View(); Generic collections and the types they contain Dart generic types are reified, which means that they carry their type information around at runtime. For example, you can test the type of collection, even in production mode: vvar nanes = new List( hames.addAl1(["Seth", ‘Kathy’, ‘Lars']); print(nanes is ListString>); // true However, the £s expression checks the type ofthe collection only—nat ofthe object might have some non-string items init. The solution isto either check each handler (see Exceptions). Inside it. In production mode, a List«string> sms type or wrap item-manipulation code in an exception Note: in contrast, generics in Java use erasure, which means that generic type parameters are removed at runtime. In Java, you ‘can test whether an object isa Lis, but you can't test whether i's a ListeString scans Language Ts 10m Restricting the parameterized type When implementing a generic type, you might want to limit the types of its parameters. You can do this using extends. /1 1 must be SonebaseClass or one of its descendants. class FoocT extends SonesaseClass> {...} class Extender extends SonetaseClass { void main() ( // It's OK to use SomeBaseClass or any of its subclasses inside <>. var soneBaseClassfoo = new Foo(); var extenderFoo = new Foo(); // It's also OK to use no <> at atl. var foo = new Foo(); 1 Specifying any non-SomeBaseClass type results in a warning and, in W/ checked mode, @ runtime error. U1 var objectFoo = new Foocobject>(); Using generic methods Initially, Dar’s generic support was limited to classes. Anewer syntax, called generic methods, allows type arguments on methods and functions: T #irstet> (ListeT> ts) ( // «+0 some initial work or error checking, then... T tmp = ts(@]s U1 «+0 some additional. checking on processing. retura tap; Here the generic type parameter on Finst (c1>) allows you to use the type argument Tin several places: + In the function's return type (7) + Inthe type of an argument (ListeT>) + Inthe type ofa local variable (T tmp) Version note: The new syntax fr generic methods was introduced in SDK 1.21, “ Ifyou use generic methods, specify an SDK version of 1.21 or higher. /tools/pub/pubspectsck-constraints) For more information about generics, see Using Generic Methods. Libraries and visibility The import and 1sbrary directives can help you create a modular and shareable code base. Libraries not only provide APIs, but area Unit of privacy: identifies that start with an underscore (_) are visible only inside the library, Every Dart app isa library, even it doesn’t use a Library directive Libraries can be distributed using packages. See Pub Package and Asset Manager (toals/pub) for information about pub, a package manager included inthe SDK. Using libraries Use inport to specify how a namespace from one library is used in the scope of another library. For example, Dart web apps generally use the dartihtml ibrary, which they can import ike this: import ‘dart:hte: The only required argument to impor‘ isa URI specifying the library. For builtin libraries, the URI has the special dart: scheme. For other libraries, you can use a fil system path or the package: scheme. The package: scheme specifies libraries provided by a package manager such asthe pub tool. For example: import ‘dart:io"s import. ‘package:mylib/nylib. dart’ import. ‘package:utils/[Link]’; Note: UR!stands for uniform resource identifier. URLs (uniform resource locators) are a common kind of URI Specifying a library prefix Ifyou import two libraries that have conflicting identifiers, then you can specify a prefix for one or both libraries. For example, if library. and ibrary2 bath have an Element las, then you might have code like this import. ‘package:1ib1/[Link]’ import ‘package:1ib2/[Link]” as 11b2; Wo Elenent elenenti = new Elenent(); U1 Uses Etement from Libt. [Link] elenent2 = new [Link](); // Uses ELement from Lib2. Importing only part of a library ifyou want to use only part of library, you can selectively import he library. UL Inport onty foo. import ‘package:1ibi/[Link]’ show foo; // Import aU names EXCEPT foo. import. ‘package:1ib2/[Link]” hide foo; Lazily loading a library Deferred loading (aso called zy loading) allows an application to load a library on demand, fand when it’s needed. Here are some cases when you might use deferred loacing + Toreduce an app'sinitial startup time. + To perform AB testing—trying out alternative implementations ofan algorithm, for example + Toload rarely used functionality, suchas optional screens and dialogs. To aaily oad a library, you must fist importitusing deferred as. import ‘package:deferred/[Link]’ deferred as hello; When you need the library, invoke loadl brary() using the library's identifier greet() async { await hello. loadLibrary(); [Link](); y In the preceding code, the await keyword pauses execution until the library is loaded. For more information about async and await, see asynchrony support. You can invoke toadtibrary() multiple times ona library without problems. The library is loaded only once. Keep in mind the following when you use deferred loading: aamaos? Language Te |O5e + Adeferredlibrary’s constants aren't constants in the importing file. Remember, these constants don't exist until the deferred library is loaded + You can’t use types from a deferred library inthe importing file. Instead, consider moving interface types to a library imported by both the deferred library and the importing fle + Dart implicitly inserts oadLibrary() into the namespace that you define using deferred as namespace. The loadt ibrary() function returns a Future (/guidesytibraies/ibrary-tour#future), Implementing libraries ‘See Create Library Packages {/guides/ibraries/ereate-library-packages) for advice on how to Implement a library package. Asynchrony support Dart has several language features to support asynchronous programming, The most commonly used of these features are async functions and avait expressions. Dart libraries ae full of functions that return Future or Stream objects. These functions are asynchronous: they return after setting up 2 possibly time-consuming operation (such as /0), without waiting fr that operation to complete. When you need to use a value represented by a Future, you have two options: + Use async and await + Use the Future API (/guides/libraries/library toursfuture) Similarly, when you need to get values from a Stream, you have two options: + Use asyne and an asynchronous for loop (await for) + Use the Stream API (/guides/ibrariesjlibrary-toursstream) Code that uses async and await is asynchronous, but it looks a ot like synchronous code. For example, here's some code that uses await to wait for the result of an asynchronous function: amait LookupVersion() Touse await, code must be in a function marked as asyne: checkversion() asyne { var version = await lookvpVersion(); Af (version == expectedversion) { U1 0 something. ) else ¢ // Do something etse. You can use try, catch, and Finally to handle errors and cleanup in code that uses await: try server = await [Link](InternetAddress..LOOPBACK_IP_V4, 4044); } catch (e) // React to inability to bind to the port. y Declaring async functions [An asyne function's a function whose body is marked with the asyne modifier. Although an async function might perform time- consuming operations, it returns immediately before any ofits body executes, checkversion() async { uw y LookUpversion() async => /* ... */; aamaos? Language Te [Ome [Adding the async keyword to a function makes it return a Future, For example, consider this synchronous function, which returns a String: ‘String LookUpversionsyne() Ifyou change it to be an async function—for example, because a future implementation wil be time consuming—the returned value isa Future: FuturecString> lookupversion() async => "1.0.0"; Note that the function's body doesn’t need to use the Future API. Dart creates the Future object if necessary. Using await expressions with Futures {An await expression has the following form: anait expression You can use await multiple times in an async function. For example, the following code waits three times forthe results of functions: var enteypoint = await findentrypoint(); var exitcode = await runéxecutable(entrypoint, args); await flushThenkxit(exitCode); In await expression, the value of expressions usually a Future; ifitisa't then the value is automatically wrapped in a Future. This Future object indicates a promise to return an object. The value of await expresston is that returned object. The await expression makes execution pause until that object is availabe. Iawait doesn’t work, make sure it’s in an async function. For example, to use await in your app's main() function, the body of mmain() must be marked as asyne: pain() asyne ( checkversion() print("In main: version is ${await lookUpversion()}"); y Using asynchronous for loops with Streams {An asynchronous for loop has the following form: await for (variable declaration in expression) { // Executes each time the strean emits 2 value. y The value of expression must have type Stream. Execution proceeds as follows: 1 Wait until the stream emits avalue. 2 Execute the body ofthe for loop, withthe variable set to that emitted value. 3. Repeat 1 and 2 until the stream is closed, To stop listening tothe stream, you can use @ break or return statement, which breaks out of the for loop and unsubscribes from the stream, Ifan asynchronous for loop doesn’t work, make sure it's in an asyne functi app'smain() function, the body of main() must be marked as async: For example, touse an asynchronous for oop in your pain() asyne ( await for (var request in requestServer) ( handleRequest (request); For more information about asynchronous programming, see the dart:asyne (/guides/librariesjlibrary-tourtdartasyne—~asynchronous- programming) section ofthe library tour. Also see the articles Dart Language Asynchrony Support: Phase 1 (/artcles/tanguage/awalt- ‘asyne) and Dart Language Asynchrony Support: Phase 2 (/atiles/language/beyondl-async), and the Dart language specification Uguides/language/spec). Callable classes To allow your Dart class tobe called like a function, implement the ¢211() method, In the following example, the WannabeFuncton class defines a call) function that takes three strings and concatenates them, separating each with a space, and appending an exclamation. Click the run button 3] to execute the code For more information on treating classes like functions, see Emulating Functions in Dart (/articles/language/emulating-functions) Isolates Modern web browsers, even on mobile platforms, run on multi-core CPUs, To take advantage ofall those cores, developers traditionally se shared-memory threads running concurrently, However, shared-state concurrency is errr prone and can lead to complicated code, Instead of threads, all Dart code runs inside of isolates. ach isolate has its own memory heap, ensuring that no isolates state is accessible from any other isolate. Typedefs In Dart, functions are objects, just ke strings and numbers are abject. A typedef or function-type alias, gives a function type a name that you can use when declaring fields and retuen types. A typedef retains type information when a function type is assigned toa variable Consider the following code, which doesn't use a typedet: class Sortedcollection { Function compare; Sortedcollection(int #(object a, Object b)) { compare = 3 // Initial, broken implementation. int sort(object a, Object b) => a; rain() { Sortedcollection coll = new Sortedcollection(sort);, U1 ALL we know is that compare is a function, // but what type of function? assert([Link] 4s Function); y ‘Type information is lost when assigning F to compare. The type of Fis (Object, Object) ~» int (where —» means returns), yet the type cof compare is Function. Ifwe change the code to use explicit names and retain type information, both developers and tools can use that information, aamaos? Language Te [Ome typedef int Conpare(Object a, object b); class Sortedcollection { Compare compare; Sortedcollection([Link]); y // Initial, broken implementation. int sort(object a, Object b) => a; rain() { ‘Sortedcollection coll = new Sortedcollection(sort);, assert([Link] is Function); assert([Link] is Compare); y Note: Currently, typedets are restricted to function types. We expect tis to change. Because typedefs are simply aliases, they offer a way to check the type of any function. For example: typedef int Compare(int a, int b); int sort(int a, int b) => a - b5 pain() { assert(sort is Compare); // True! y New function type syntax: Dart 1.24 introduced a new form of function types, the generic function type alias. You might use this Feature f you pass around generic methods, define field that are function types, or define arguments with generic function types. Here's an example of using the new syntax: typedef F = ListeT> Function <1>(1); Metadata Use metadata to give additional information about your code. A metadata annotation begins with the character 8, fllowed by either a reference toa compile-time constant (such as deprecated) or acallto a constant constructor. Three annotations are available toa Dart code: deprecated, override, and Goroxy. For examples of using override and Goroxy, see Extending a class. Here's an example of using the @éeprecated annotation class Television ( U1 Deprecated: Use [turndn} instead._ deprecated void activate() { rnon(); U1 Turns the TV's power on void turnon() { print(‘on!"); You can define your own metadata annotations. Here's an example of defining a @todo annotation that takes two arguments: aamaos? Language Te [Ome Library todo; class todo ( Final String who; final String whats const todo([Link], this-what); y ‘And here's an example of using that import. ‘todo. dart” 5 Gtodo('seth’, ‘rake this do sorething') void dosonething() { print(‘do something"); y Metadata can appear before a library, class, typedet, type parameter, constructor, factory, function, field, parameter, or variable declaration and before an import or export directive. You can retrieve metadata at runtime using reflection. Comments Dart supports single-line comments, multi-line comments, and documentation comments. Single-line comments Asingle-line comment begins with //. Everything between // and the end of line is ignored by the Dart compiler. ratn() { // 1000: refactor into an AbstractLLomaGreetingFactory? print(‘Welcome to my Lana farm!'); y Multi-line comments. Amultitine comment begins with /* and ends with */. Everything between /* and */ is ignored by the Dart compiler (unless the comments a documentation comment; see the next section). Multiline comments can nest pain() ¢ ” + This is a Lot of work. Consider raising chickens. lana Larry = new Ltana(); lorry. feed(); [Link](); Larry. clean(); ” Documentation comments Documentation comments are multiline or single-tine comments that begin with /// or /**. Using /// on consecutive lines has the same effect as a multi-line doc comment. Inside a documentation comment, the Dart compiler ignores all text unless its enclosed in brackets. Using brackets, you can refer to classes, methods, fields, top-level variables, functions, ané parameters. The names in brackets are resolved inthe lexical scope of the documented program element. Here is an example of documentation comments with references to other classes and arguments: UI A donesticated South American comeLid (Lama gloma). Ws //1 Andean cultures have used Llanas as meat and pack U/1 animals since pre-Hispanic tines class Llama ( String nane; U1 Feeds your Llama [Food] UW /// The typical. Llona eats one bale of hay per week. void feed(Food food) { uw U1 bxercises your Ltana with an [activity] for U1 [eimeltmit] minutes. void exercise(Activity activity, int tineLinit) { In the generated documentation, (Faod] becomes a link tothe API docs forthe Food class To parse Dart code and generate HTML documentation, you can use the SDKs documentation generation tool.” Foran example of generated documentation, see the Dart AP| documentation. ” For advice on how to structure your comments, see Guidelines for Dart Doc Comments. (/guides/tanguage/effective-dart/documentation) Summary This page summarized the commonly used features inthe Dart language. More features are being implemented, but we expect that they won't break existing code, For more information, see the Dart Language Specification (/gides/language/spec) and Effective Dart Uguidesslanguageletfective-dart To learn more about Dart’s core libraries, see A Tour ofthe Dart Libraries (/guidesylibraries/ibrary-tour)

You might also like