Chức năng ẩn danh trong php geeksforgeeks

Arrow functions support the same features as anonymous functions, except that using variables from the parent scope is always automatic

Show

Khi một biến được sử dụng trong biểu thức được xác định trong phạm vi cha, nó sẽ được ngầm định theo giá trị. Trong ví dụ sau, các hàm $fn1 và $fn2 hoạt động giống nhau

Example #1 Arrow functions capture variables by value automatically

$y = 1;

$fn1 = fn($x) => $x + $y;
// equivalent to using $y by value:
$fn2 = function ($x) use ($y) {
return $x + $y;
};

var_export($fn1(3));
?>

The above example will output

This also works if the arrow functions are nested

Example #2 Arrow functions capture variables by value automatically, even when nested

$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// Outputs 51
var_export($fn(5)(10));
?>

Tương tự như các hàm ẩn danh, cú pháp hàm mũi tên cho phép các chữ ký hàm tùy ý, bao gồm tham số và kiểu trả về, giá trị mặc định, biến thể, cũng như chuyển và trả về tham chiếu theo tham chiếu. Tất cả những điều sau đây là ví dụ hợp lệ của các chức năng mũi tên

Ví dụ #3 Ví dụ về hàm mũi tên

fn(array $x) => $x;
static fn(): int => $x;
fn($x = 42) => $x;
fn(&$x) => $x;
fn&($x) => $x;
fn($x, ...$rest) => $rest;

?>

Các hàm mũi tên sử dụng liên kết biến theo giá trị. Điều này gần tương đương với việc thực hiện một use($x) cho mọi biến $x được sử dụng bên trong hàm mũi tên. Liên kết theo giá trị có nghĩa là không thể sửa đổi bất kỳ giá trị nào từ phạm vi bên ngoài. Các hàm ẩn danh có thể được sử dụng thay thế cho các ràng buộc by-ref

Trang này chỉ cho bạn cách sử dụng từng tính năng chính của Dart, từ các biến và toán tử đến các lớp và thư viện, với giả định rằng bạn đã biết cách lập trình bằng ngôn ngữ khác. Để có phần giới thiệu ngắn gọn hơn, ít đầy đủ hơn về ngôn ngữ, hãy xem trang mẫu ngôn ngữ

Để tìm hiểu thêm về các thư viện cốt lõi của Dart, hãy xem chuyến tham quan thư viện. Bất cứ khi nào bạn muốn biết thêm chi tiết về một tính năng ngôn ngữ, hãy tham khảo đặc tả ngôn ngữ Dart

Ghi chú. Bạn có thể chơi với hầu hết các tính năng ngôn ngữ của Dart bằng DartPad (tìm hiểu thêm). Mở DartPad

Trang này sử dụng DartPads được nhúng để hiển thị một số ví dụ. Nếu bạn thấy các ô trống thay vì DartPad, hãy truy cập trang xử lý sự cố DartPad

Một chương trình phi tiêu cơ bản

Đoạn mã sau sử dụng nhiều tính năng cơ bản nhất của Dart

// Define a function.
void printInteger(int aNumber) {
  print('The number is $aNumber.'); // Print to console.
}

// This is where the app starts executing.
void main() {
  var number = 42; // Declare and initialize a variable.
  printInteger(number); // Call a function.
}

Đây là những gì chương trình này sử dụng áp dụng cho tất cả (hoặc gần như tất cả) ứng dụng Phi tiêu

Object name = 'Bob';
14Nhận xét một dòng. Dart cũng hỗ trợ nhận xét nhiều dòng và tài liệu. Để biết chi tiết, xem.
Object name = 'Bob';
15Một loại đặc biệt cho biết một giá trị không bao giờ được sử dụng. Các hàm như
Object name = 'Bob';
16 và
Object name = 'Bob';
17 không trả về giá trị một cách rõ ràng có kiểu trả về
Object name = 'Bob';
15.
Object name = 'Bob';
19Loại khác, biểu thị số nguyên. Một số bổ sung là
Object name = 'Bob';
20,
Object name = 'Bob';
21 và
Object name = 'Bob';
22.
Object name = 'Bob';
23Một số chữ. Số chữ là một loại hằng số thời gian biên dịch.
Object name = 'Bob';
24Một cách thuận tiện để hiển thị đầu ra.
Object name = 'Bob';
25 (hoặc
Object name = 'Bob';
26)Một chuỗi ký tự.
Object name = 'Bob';
27 (hoặc
Object name = 'Bob';
28)Nội suy chuỗi. bao gồm một biến hoặc chuỗi của biểu thức tương đương bên trong một chuỗi ký tự. For more information, see .
Object name = 'Bob';
17Chức năng cấp cao nhất, bắt buộc, đặc biệt nơi bắt đầu thực thi ứng dụng. Để biết thêm thông tin, xem.
Object name = 'Bob';
30Một cách để khai báo một biến mà không chỉ định loại của nó. Loại của biến này (
Object name = 'Bob';
19) được xác định bởi giá trị ban đầu của nó (
Object name = 'Bob';
23)

Ghi chú. Mã của trang web này tuân theo các quy ước trong hướng dẫn kiểu Dart

khái niệm quan trọng

Khi bạn tìm hiểu về ngôn ngữ Dart, hãy ghi nhớ những thông tin và khái niệm này

  • Mọi thứ bạn có thể đặt trong một biến đều là một đối tượng và mọi đối tượng đều là một thể hiện của một lớp. Số chẵn, hàm số và

    Object name = 'Bob';
    33 là đối tượng. Ngoại trừ
    Object name = 'Bob';
    33 (nếu bạn bật sound null safety), tất cả các đối tượng kế thừa từ lớp
    Object name = 'Bob';
    35

    ghi chú phiên bản. An toàn vô hiệu đã được giới thiệu trong Dart 2. 12. Sử dụng an toàn null yêu cầu ít nhất 2. 12

  • Mặc dù Dart được gõ mạnh, chú thích loại là tùy chọn vì Dart có thể suy ra các loại. In the code above,

    Object name = 'Bob';
    36 is inferred to be of type
    Object name = 'Bob';
    19

  • Nếu bạn bật tính năng an toàn vô hiệu, các biến không thể chứa

    Object name = 'Bob';
    33 trừ khi bạn cho biết chúng có thể. Bạn có thể biến một biến thành vô giá trị bằng cách đặt một dấu chấm hỏi (
    Object name = 'Bob';
    39) ở cuối kiểu của nó. Ví dụ: một biến kiểu
    Object name = 'Bob';
    40 có thể là số nguyên hoặc có thể là
    Object name = 'Bob';
    33. Nếu bạn biết rằng một biểu thức không bao giờ có giá trị là
    Object name = 'Bob';
    33 nhưng Dart không đồng ý, bạn có thể thêm
    Object name = 'Bob';
    43 để khẳng định rằng nó không rỗng (và để đưa ra một ngoại lệ nếu có). Một ví dụ.
    Object name = 'Bob';
    44

  • When you want to explicitly say that any type is allowed, use the type

    Object name = 'Bob';
    45 (if you’ve ),
    Object name = 'Bob';
    35, or—if you must defer type checking until runtime—the

  • Dart supports generic types, like

    Object name = 'Bob';
    48 (a list of integers) or
    Object name = 'Bob';
    49 (a list of objects of any type)

  • Dart supports top-level functions (such as

    Object name = 'Bob';
    17), as well as functions tied to a class or object (static and 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 to a class or object (static and instance variables). Instance variables are sometimes known as fields or properties

  • Không giống như Java, Dart không có các từ khóa

    Object name = 'Bob';
    51,
    Object name = 'Bob';
    52 và
    Object name = 'Bob';
    53. If an identifier starts with an underscore (
    Object name = 'Bob';
    54), it’s private to its library. For details, see

  • Identifiers can start with a letter or underscore (

    Object name = 'Bob';
    54), followed by any combination of those characters plus digits

  • Dart has both expressions (which have runtime values) and statements (which don’t). For example, the

    Object name = 'Bob';
    56 has a value of
    Object name = 'Bob';
    57 or
    Object name = 'Bob';
    58. Compare that to an , which has no value. A statement often contains one or more expressions, but an expression can’t directly contain a statement

  • 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; a run-time error results in an being raised while the code executes

Keywords

The following table lists the words that the Dart language treats specially

 2 2 1 2 2export 2 2 1 3 2 2 1 2 2 2 2 1 2 2 2 2 2 2 2 2 1 3 2 2 2 

Avoid using these words as identifiers. However, if necessary, the keywords marked with superscripts can be identifiers

  • Words with the superscript 1 are contextual keywords, which have meaning only in specific places. They’re valid identifiers everywhere

  • Words with the superscript 2 are built-in identifiers. These keywords are valid identifiers in most places, but they can’t be used as class or type names, or as import prefixes

  • Words with the superscript 3 are limited reserved words related to . You can’t use

    Object name = 'Bob';
    59 or
    Object name = 'Bob';
    60 as an identifier in any function body marked with
    Object name = 'Bob';
    61,
    Object name = 'Bob';
    62, or
    Object name = 'Bob';
    63

All other words in the table are reserved words, which can’t be identifiers

Variables

Here’s an example of creating a variable and initializing it

var name = 'Bob';

Variables store references. The variable called

Object name = 'Bob';
64 contains a reference to a
Object name = 'Bob';
20 object with a value of “Bob”

The type of the

Object name = 'Bob';
64 variable is inferred to be
Object name = 'Bob';
20, but you can change that type by specifying it. If an object isn’t restricted to a single type, specify the
Object name = 'Bob';
35 type (or
Object name = 'Bob';
47 if necessary)

Object name = 'Bob';

Một tùy chọn khác là khai báo rõ ràng loại sẽ được suy ra

String name = 'Bob';

Note. This page follows the of using

Object name = 'Bob';
30, rather than type annotations, for local variables

Default value

Uninitialized variables that have a nullable type have an initial value of

Object name = 'Bob';
33. (If you haven’t opted into null safety, then every variable has a nullable type. ) Even variables with numeric types are initially null, because numbers—like everything else in Dart—are objects

int? lineCount;
assert(lineCount == null);

Note. Production code ignores the

Object name = 'Bob';
72 call. During development, on the other hand,
Object name = 'Bob';
73 throws an exception if condition is false. For details, see

If you enable null safety, then you must initialize the values of non-nullable variables before you use them

int lineCount = 0;

You don’t have to initialize a local variable where it’s declared, but you do need to assign it a value before it’s used. For example, the following code is valid because Dart can detect that

Object name = 'Bob';
74 is non-null by the time it’s passed to
Object name = 'Bob';
24

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);

Top-level and class variables are lazily initialized; the initialization code runs the first time the variable is used

Late variables

Dart 2. 12 added the

Object name = 'Bob';
76 modifier, which has two use cases

  • Declaring a non-nullable variable that’s initialized after its declaration
  • Lazily initializing a variable

Often Dart’s control flow analysis can detect when a non-nullable variable is set to a non-null value before it’s used, but sometimes analysis fails. Two common cases are top-level variables and instance variables. Dart often can’t determine whether they’re set, so it doesn’t try

If you’re sure that a variable is set before it’s used, but Dart disagrees, you can fix the error by marking the variable as

Object name = 'Bob';
76

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}

If you fail to initialize a

Object name = 'Bob';
76 variable, a runtime error occurs when the variable is used

When you mark a variable as

Object name = 'Bob';
76 but initialize it at its declaration, then the initializer runs the first time the variable is used. This lazy initialization is handy in a couple of cases

  • The variable might not be needed, and initializing it is costly
  • You’re initializing an instance variable, and its initializer needs access to
    Object name = 'Bob';
    80

In the following example, if the

Object name = 'Bob';
81 variable is never used, then the expensive
Object name = 'Bob';
82 function is never called

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.

Final and const

If you never intend to change a variable, use

Object name = 'Bob';
83 or
Object name = 'Bob';
84, either instead of
Object name = 'Bob';
30 or in addition to a type. A final variable can be set only once; a const variable is a compile-time constant. (Const variables are implicitly final. )

Note. can be

Object name = 'Bob';
83 but not
Object name = 'Bob';
84

Here’s an example of creating and setting a

Object name = 'Bob';
83 variable

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';

You can’t change the value of a

Object name = 'Bob';
83 variable

var name = 'Bob';
0

Sử dụng

Object name = 'Bob';
84 cho các biến mà bạn muốn là hằng số thời gian biên dịch. If the const variable is at the class level, mark it
Object name = 'Bob';
91. Where you declare the variable, set the value to a compile-time constant such as a number or string literal, a const variable, or the result of an arithmetic operation on constant numbers

var name = 'Bob';
1

The

Object name = 'Bob';
84 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

var name = 'Bob';
2

You can omit

Object name = 'Bob';
84 from the initializing expression of a
Object name = 'Bob';
84 declaration, like for
Object name = 'Bob';
95 above. For details, see

You can change the value of a non-final, non-const variable, even if it used to have a

Object name = 'Bob';
84 value

var name = 'Bob';
3

You can’t change the value of a

Object name = 'Bob';
84 variable

var name = 'Bob';
4

You can define constants that use (

Object name = 'Bob';
98 and
Object name = 'Bob';
99), , and (
String name = 'Bob';
01 and
String name = 'Bob';
02)

var name = 'Bob';
5

Note. Although a

Object name = 'Bob';
83 object cannot be modified, its fields can be changed. In comparison, a
Object name = 'Bob';
84 object and its fields cannot be changed. they’re immutable

For more information on using

Object name = 'Bob';
84 to create constant values, see , , and

Built-in types

The Dart language has special support for the following

  • (
    Object name = 'Bob';
    19,
    String name = 'Bob';
    07)
  • (
    Object name = 'Bob';
    20)
  • (
    Object name = 'Bob';
    22)
  • (
    Object name = 'Bob';
    21, also known as arrays)
  • (
    String name = 'Bob';
    11)
  • (
    String name = 'Bob';
    12)
  • (
    String name = 'Bob';
    13; often replaced by the
    String name = 'Bob';
    14 API)
  • (
    String name = 'Bob';
    15)
  • The value
    Object name = 'Bob';
    33 (
    String name = 'Bob';
    17)

This support includes the ability to create objects using literals. For example,

String name = 'Bob';
18 is a string literal, and
String name = 'Bob';
19 is a boolean literal

Bởi vì mọi biến trong Dart đề cập đến một đối tượng—một thể hiện của một lớp—bạn thường có thể sử dụng các hàm tạo để khởi tạo các biến. Some of the built-in types have their own constructors. For example, you can use the

String name = 'Bob';
20 constructor to create a map

Some other types also have special roles in the Dart language

  • Object name = 'Bob';
    35. The superclass of all Dart classes except
    String name = 'Bob';
    17
  • String name = 'Bob';
    23. The superclass of all enums
  • String name = 'Bob';
    24 and
    String name = 'Bob';
    25. Used in
  • String name = 'Bob';
    26. Used in and in synchronous
  • String name = 'Bob';
    27. Indicates that an expression can never successfully finish evaluating. Most often used for functions that always throw an exception
  • Object name = 'Bob';
    47. Indicates that you want to disable static checking. Usually you should use
    Object name = 'Bob';
    35 or
    Object name = 'Bob';
    45 instead
  • Object name = 'Bob';
    15. Indicates that a value is never used. Often used as a return type

The

Object name = 'Bob';
35,
Object name = 'Bob';
45,
String name = 'Bob';
17, and
String name = 'Bob';
27 classes have special roles in the class hierarchy, as described in the section of Understanding null safety

Numbers

Dart numbers come in two flavors

Object name = 'Bob';
19

Integer values no larger than 64 bits, depending on the platform. On native platforms, values can be from -263 to 263 - 1. On the web, integer values are represented as JavaScript numbers (64-bit floating-point values with no fractional part) and can be from -253 to 253 - 1

String name = 'Bob';
07

64-bit (double-precision) floating-point numbers, as specified by the IEEE 754 standard

Both

Object name = 'Bob';
19 and
String name = 'Bob';
07 are subtypes of
String name = 'Bob';
40. The num type includes basic operators such as +, -, /, and *, and is also where you’ll find
String name = 'Bob';
41,
String name = 'Bob';
42, and
String name = 'Bob';
43, among other methods. (Bitwise operators, such as >>, are defined in the
Object name = 'Bob';
19 class. ) If num and its subtypes don’t have what you’re looking for, the dart. math library might

Số nguyên là số không có dấu thập phân. Here are some examples of defining integer literals

var name = 'Bob';
6

If a number includes a decimal, it is a double. Here are some examples of defining double literals

var name = 'Bob';
7

You can also declare a variable as a num. If you do this, the variable can have both integer and double values

var name = 'Bob';
8

Integer literals are automatically converted to doubles when necessary

var name = 'Bob';
9

Here’s how you turn a string into a number, or vice versa

Object name = 'Bob';
0

The

Object name = 'Bob';
19 type specifies the traditional bitwise shift (
String name = 'Bob';
46,
String name = 'Bob';
47,
String name = 'Bob';
48), complement (
String name = 'Bob';
49), AND (
String name = 'Bob';
50), OR (
String name = 'Bob';
51), and XOR (
String name = 'Bob';
52) operators, which are useful for manipulating and masking flags in bit fields. For example

Object name = 'Bob';
1

For more examples, see the section

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

Object name = 'Bob';
2

For more information, see Numbers in Dart

Strings

A Dart string (

Object name = 'Bob';
20 object) holds a sequence of UTF-16 code units. You can use either single or double quotes to create a string

Object name = 'Bob';
3

You can put the value of an expression inside a string by using

String name = 'Bob';
54
String name = 'Bob';
55
String name = 'Bob';
56. If the expression is an identifier, you can skip the {}. To get the string corresponding to an object, Dart calls the object’s
String name = 'Bob';
57 method

Object name = 'Bob';
4

Note. The

String name = 'Bob';
58 operator tests whether two objects are equivalent. Two strings are equivalent if they contain the same sequence of code units

You can concatenate strings using adjacent string literals or the

String name = 'Bob';
59 operator

Object name = 'Bob';
5

Another way to create a multi-line string. use a triple quote with either single or double quotation marks

Object name = 'Bob';
6

You can create a “raw” string by prefixing it with

String name = 'Bob';
60

Object name = 'Bob';
7

See for details on how to express Unicode characters in a string

Literal strings are compile-time constants, as long as any interpolated expression is a compile-time constant that evaluates to null or a numeric, string, or boolean value

Object name = 'Bob';
8

For more information on using strings, see

Booleans

To represent boolean values, Dart has a type named

Object name = 'Bob';
22. Only two objects have type bool. the boolean literals
String name = 'Bob';
19 and
String name = 'Bob';
63, which are both compile-time constants

Dart’s type safety means that you can’t use code like

String name = 'Bob';
64 or
String name = 'Bob';
65. Instead, explicitly check for values, like this

Object name = 'Bob';
9

Lists

Perhaps the most common collection in nearly every programming language is the array, or ordered group of objects. In Dart, arrays are

Object name = 'Bob';
21 objects, so most people just call them lists

Dart list literals are denoted by a comma separated list of expressions or values, enclosed in square brackets (

String name = 'Bob';
67). Here’s a simple Dart list

String name = 'Bob';
0

Note. Dart infers that

String name = 'Bob';
68 has type
Object name = 'Bob';
48. If you try to add non-integer objects to this list, the analyzer or runtime raises an error. For more information, read about

You can add a comma after the last item in a Dart collection literal. This trailing comma doesn’t affect the collection, but it can help prevent copy-paste errors

String name = 'Bob';
1

Lists use zero-based indexing, where 0 is the index of the first value and

String name = 'Bob';
70 is the index of the last value. You can get a list’s length using the
String name = 'Bob';
71 property and access a list’s values using the subscript operator (
String name = 'Bob';
67)

String name = 'Bob';
2

To create a list that’s a compile-time constant, add

Object name = 'Bob';
84 before the list literal

String name = 'Bob';
3

Dart supports the spread operator (

String name = 'Bob';
01) and the null-aware spread operator (
String name = 'Bob';
02), which provide a concise way to insert multiple values into a collection

For example, you can use the spread operator (

String name = 'Bob';
01) to insert all the values of a list into another list

String name = 'Bob';
4

If the expression to the right of the spread operator might be null, you can avoid exceptions by using a null-aware spread operator (

String name = 'Bob';
02)

String name = 'Bob';
5

For more details and examples of using the spread operator, see the spread operator proposal

Dart also offers collection if and collection for, which you can use to build collections using conditionals (

String name = 'Bob';
00) and repetition (
String name = 'Bob';
79)

Here’s an example of using collection if to create a list with three or four items in it

String name = 'Bob';
6

Here’s an example of using collection for to manipulate the items of a list before adding them to another list

String name = 'Bob';
7

For more details and examples of using collection

String name = 'Bob';
00 and
String name = 'Bob';
79, see the control flow collections proposal

The List type has many handy methods for manipulating lists. For more information about lists, see and

Sets

A set in Dart is an unordered collection of unique items. Dart support for sets is provided by set literals and the

String name = 'Bob';
11 type

Here is a simple Dart set, created using a set literal

String name = 'Bob';
8

Note. Dart infers that

String name = 'Bob';
83 has the type
String name = 'Bob';
84. If you try to add the wrong type of value to the set, the analyzer or runtime raises an error. For more information, read about

To create an empty set, use

String name = 'Bob';
85 preceded by a type argument, or assign
String name = 'Bob';
85 to a variable of type
String name = 'Bob';
11

String name = 'Bob';
9

Set or map? The syntax for map literals is similar to that for set literals. Because map literals came first,

String name = 'Bob';
85 defaults to the
String name = 'Bob';
12 type. If you forget the type annotation on
String name = 'Bob';
85 or the variable it’s assigned to, then Dart creates an object of type
String name = 'Bob';
91

Add items to an existing set using the

String name = 'Bob';
92 or
String name = 'Bob';
93 methods

int? lineCount;
assert(lineCount == null);
0

Use

String name = 'Bob';
71 to get the number of items in the set

int? lineCount;
assert(lineCount == null);
1

To create a set that’s a compile-time constant, add

Object name = 'Bob';
84 before the set literal

int? lineCount;
assert(lineCount == null);
2

Sets support spread operators (

String name = 'Bob';
01 and
String name = 'Bob';
02) and collection
String name = 'Bob';
00 and
String name = 'Bob';
79, just like lists do. For more information, see the and discussions

For more information about sets, see and

Maps

In general, a map is an object that associates keys and values. Cả khóa và giá trị đều có thể là bất kỳ loại đối tượng nào. Mỗi khóa chỉ xuất hiện một lần nhưng bạn có thể sử dụng cùng một giá trị nhiều lần. Hỗ trợ phi tiêu cho bản đồ được cung cấp bởi chữ bản đồ và loại

String name = 'Bob';
12

Dưới đây là một vài bản đồ Phi tiêu đơn giản, được tạo bằng chữ bản đồ

int? lineCount;
assert(lineCount == null);
3

Ghi chú. Phi tiêu suy ra rằng

int? lineCount;
assert(lineCount == null);
01 có loại
int? lineCount;
assert(lineCount == null);
02 và
int? lineCount;
assert(lineCount == null);
03 có loại
int? lineCount;
assert(lineCount == null);
04. Nếu bạn cố gắng thêm loại giá trị sai vào bản đồ, bộ phân tích hoặc bộ thực thi sẽ phát sinh lỗi. Để biết thêm thông tin, đọc về

Bạn có thể tạo các đối tượng giống nhau bằng cách sử dụng hàm tạo Bản đồ

int? lineCount;
assert(lineCount == null);
4

Ghi chú. Nếu bạn đến từ một ngôn ngữ như C# hoặc Java, bạn có thể sẽ thấy

int? lineCount;
assert(lineCount == null);
05 thay vì chỉ
String name = 'Bob';
20. Trong Dart, từ khóa
int? lineCount;
assert(lineCount == null);
07 là tùy chọn. Để biết chi tiết, xem

Thêm cặp khóa-giá trị mới vào bản đồ hiện có bằng cách sử dụng toán tử gán chỉ số dưới (

int? lineCount;
assert(lineCount == null);
08)

int? lineCount;
assert(lineCount == null);
5

Truy xuất một giá trị từ bản đồ bằng toán tử chỉ số dưới (

String name = 'Bob';
67)

int? lineCount;
assert(lineCount == null);
6

Nếu bạn tìm một chiếc chìa khóa không có trong bản đồ, bạn sẽ nhận lại được

Object name = 'Bob';
33

int? lineCount;
assert(lineCount == null);
7

Sử dụng

String name = 'Bob';
71 để nhận số cặp khóa-giá trị trong bản đồ

int? lineCount;
assert(lineCount == null);
8

Để tạo bản đồ là hằng số thời gian biên dịch, hãy thêm

Object name = 'Bob';
84 trước chữ bản đồ

int? lineCount;
assert(lineCount == null);
9

Bản đồ hỗ trợ các toán tử trải rộng (

String name = 'Bob';
01 và
String name = 'Bob';
02) và bộ sưu tập
String name = 'Bob';
00 và
String name = 'Bob';
79, giống như danh sách. Để biết chi tiết và ví dụ, hãy xem đề xuất toán tử trải rộng và đề xuất bộ sưu tập luồng điều khiển

Để biết thêm thông tin về bản đồ, hãy xem phần và phạm vi bảo hiểm của chuyến tham quan thư viện về

Các cụm rune và grapheme

In Dart, runes expose the Unicode code points of a string. You can use the characters package to view or manipulate user-perceived characters, also known as

Unicode defines a unique numeric value for each letter, digit, and symbol used in all of the world’s writing systems. Because a Dart string is a sequence of UTF-16 code units, expressing Unicode code points within a string requires special syntax. The usual way to express a Unicode code point is

int? lineCount;
assert(lineCount == null);
18, where XXXX is a 4-digit hexadecimal value. Ví dụ, ký tự trái tim (♥) là
int? lineCount;
assert(lineCount == null);
19. To specify more or less than 4 hex digits, place the value in curly brackets. For example, the laughing emoji (😆) is
int? lineCount;
assert(lineCount == null);
20

If you need to read or write individual Unicode characters, use the

String name = 'Bob';
14 getter defined on String by the characters package. The returned
int? lineCount;
assert(lineCount == null);
22 object is the string as a sequence of grapheme clusters. Here’s an example of using the characters API

int lineCount = 0;
0

The output, depending on your environment, looks something like this

int lineCount = 0;
1

For details on using the characters package to manipulate strings, see the example and API reference for the characters package

Symbols

A

String name = 'Bob';
15 object represents an operator or identifier declared 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 literal, which is just

int? lineCount;
assert(lineCount == null);
24 followed by the identifier

int lineCount = 0;
2

Symbol literals are compile-time constants

Functions

Dart is a 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 of a Dart class as if it were a function. For details, see

Here’s an example of implementing a function

int lineCount = 0;
3

Although Effective Dart recommends , the function still works if you omit the types

int lineCount = 0;
4

For functions that contain just one expression, you can use a shorthand syntax

int lineCount = 0;
5

The

int? lineCount;
assert(lineCount == null);
25 syntax is a shorthand for
int? lineCount;
assert(lineCount == null);
26. The
int? lineCount;
assert(lineCount == null);
27 notation is sometimes referred to as arrow syntax

Note. Only an expression—not a statement—can appear between the arrow (=>) and the semicolon (;). For example, you can’t put an there, but you can use a

Parameters

A function can have any number of required positional parameters. These can be followed either by named parameters or by optional positional parameters (but not both)

Note. Some APIs—notably Flutter widget constructors—use only named parameters, even for parameters that are mandatory. See the next section for details

You can use when you pass arguments to a function or when you define function parameters

Named parameters

Named parameters are optional unless they’re explicitly marked as

int? lineCount;
assert(lineCount == null);
28

When defining a function, use

int? lineCount;
assert(lineCount == null);
29 to specify named parameters. If you don’t provide a default value or mark a named parameter as
int? lineCount;
assert(lineCount == null);
28, their types must be nullable as their default value will be
Object name = 'Bob';
33

int lineCount = 0;
6

When calling a function, you can specify named arguments using

int? lineCount;
assert(lineCount == null);
32. For example

int lineCount = 0;
7

To define a default value for a named parameter besides

Object name = 'Bob';
33, use
int? lineCount;
assert(lineCount == null);
34 to specify a default value. The specified value must be a compile-time constant. For example

int lineCount = 0;
8

If you instead want a named parameter to be mandatory, requiring callers to provide a value for the parameter, annotate them with

int? lineCount;
assert(lineCount == null);
28

int lineCount = 0;
9

If someone tries to create a

int? lineCount;
assert(lineCount == null);
36 without specifying the
int? lineCount;
assert(lineCount == null);
37 argument, then the analyzer reports an issue

Note. A parameter marked as

int? lineCount;
assert(lineCount == null);
28 can still be nullable

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
0

You might want to place positional arguments first, but Dart doesn’t require it. Dart allows named arguments to be placed anywhere in the argument list when it suits your API

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
1

Optional positional parameters

Wrapping a set of function parameters in

String name = 'Bob';
67 marks them as optional positional parameters. If you don’t provide a default value, their types must be nullable as their default value will be
Object name = 'Bob';
33

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
2

Here’s an example of calling this function without the optional parameter

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
3

And here’s an example of calling this function with the third parameter

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
4

To define a default value for an optional positional parameter besides

Object name = 'Bob';
33, use
int? lineCount;
assert(lineCount == null);
34 to specify a default value. Giá trị được chỉ định phải là hằng số thời gian biên dịch. For example

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
5

The main() function

Every app must have a top-level

Object name = 'Bob';
17 function, which serves as the entrypoint to the app. The
Object name = 'Bob';
17 function returns
Object name = 'Bob';
15 and has an optional
int? lineCount;
assert(lineCount == null);
46 parameter for arguments

Here’s a simple

Object name = 'Bob';
17 function

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
6

Here’s an example of the

Object name = 'Bob';
17 function for a command-line app that takes arguments

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
7

You can use the args library to define and parse command-line arguments

Functions as first-class objects

You can pass a function as a parameter to another function. For example

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
8

You can also assign a function to a variable, such as

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
9

This example uses an anonymous function. More about those in the next section

Anonymous functions

Most functions are named, such as

Object name = 'Bob';
17 or
int? lineCount;
assert(lineCount == null);
50. You can also create a nameless function called an anonymous function, or 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 optional type annotations, between parentheses

The code block that follows contains the function’s body

int? lineCount;
assert(lineCount == null);
51

The following example defines an anonymous function with an untyped parameter,

int? lineCount;
assert(lineCount == null);
52, and passes it to the
int? lineCount;
assert(lineCount == null);
53 function. The function, invoked for each item in the list, converts each string to uppercase. Then in the anonymous function passed to
int? lineCount;
assert(lineCount == null);
54, each converted string is printed out alongside its length

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
0

Click Run to execute the code

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
1

Nếu hàm chỉ chứa một biểu thức hoặc câu lệnh trả về, bạn có thể rút gọn nó bằng cách sử dụng ký hiệu mũi tên. Dán dòng sau vào DartPad và nhấp vào Chạy để xác minh rằng nó có chức năng tương đương

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
2

Lexical scope

Dart is a lexically scoped language, which means that the scope of variables is determined statically, simply by the layout of the code. Bạn có thể “đi theo dấu ngoặc nhọn ra ngoài” để xem một biến có nằm trong phạm vi không

Here is an example of nested functions with variables at each scope level

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
3

Notice how

int? lineCount;
assert(lineCount == null);
55 can use variables from every level, all the way up to the top level

Đóng từ vựng

Bao đóng là một đối tượng hàm có quyền truy cập vào các biến trong phạm vi từ vựng của nó, ngay cả khi hàm được sử dụng bên ngoài phạm vi ban đầu của nó

Các chức năng có thể đóng trên các biến được xác định trong phạm vi xung quanh. Trong ví dụ sau,

int? lineCount;
assert(lineCount == null);
56 nắm bắt biến
int? lineCount;
assert(lineCount == null);
57. Hàm được trả về đi đến đâu, nó ghi nhớ
int? lineCount;
assert(lineCount == null);
57

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
4

Các chức năng kiểm tra cho bình đẳng

Đây là một ví dụ về kiểm tra các hàm cấp cao nhất, các phương thức tĩnh và các phương thức thể hiện cho sự bình đẳng

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
5

Giá trị trả về

Tất cả các chức năng trả về một giá trị. Nếu không có giá trị trả về nào được chỉ định, câu lệnh

int? lineCount;
assert(lineCount == null);
59 được ngầm thêm vào thân hàm

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
6

nhà điều hành

Dart hỗ trợ các toán tử được hiển thị trong bảng sau. Bảng hiển thị tính kết hợp toán tử của Dart và từ cao nhất đến thấp nhất, là một xấp xỉ của các mối quan hệ toán tử của Dart. Bạn có thể thực hiện nhiều trong số này

DescriptionOperatorAssociativityunary postfix
int? lineCount;
assert(lineCount == null);
60   
int? lineCount;
assert(lineCount == null);
61   
int? lineCount;
assert(lineCount == null);
62   
String name = 'Bob';
67   
int? lineCount;
assert(lineCount == null);
64   
int? lineCount;
assert(lineCount == null);
65   
int? lineCount;
assert(lineCount == null);
66   
Object name = 'Bob';
43Noneunary prefix
int? lineCount;
assert(lineCount == null);
68   
int? lineCount;
assert(lineCount == null);
69   
int? lineCount;
assert(lineCount == null);
70   
int? lineCount;
assert(lineCount == null);
71   
int? lineCount;
assert(lineCount == null);
72     
int? lineCount;
assert(lineCount == null);
73   Nonemultiplicative
int? lineCount;
assert(lineCount == null);
74   
int? lineCount;
assert(lineCount == null);
75   
int? lineCount;
assert(lineCount == null);
76  
int? lineCount;
assert(lineCount == null);
77Leftadditive
String name = 'Bob';
59   
int? lineCount;
assert(lineCount == null);
79Leftshift
String name = 'Bob';
46   
String name = 'Bob';
47   
String name = 'Bob';
48Leftbitwise AND
String name = 'Bob';
50Leftbitwise XOR
String name = 'Bob';
52Leftbitwise OR
String name = 'Bob';
51Leftrelational and type test
int? lineCount;
assert(lineCount == null);
86   
int? lineCount;
assert(lineCount == null);
87   
int? lineCount;
assert(lineCount == null);
88   
int? lineCount;
assert(lineCount == null);
89   
Object name = 'Bob';
99   
Object name = 'Bob';
98   
int? lineCount;
assert(lineCount == null);
92Noneequality
String name = 'Bob';
58   
int? lineCount;
assert(lineCount == null);
94   Nonelogical AND
int? lineCount;
assert(lineCount == null);
95Leftlogical OR . Đúng

Cảnh báo. Bảng trước chỉ nên được sử dụng như một hướng dẫn hữu ích. Khái niệm về ưu tiên toán tử và tính kết hợp là một xấp xỉ của sự thật được tìm thấy trong ngữ pháp ngôn ngữ. Bạn có thể tìm thấy hành vi có thẩm quyền của các mối quan hệ toán tử của Dart trong ngữ pháp được xác định trong đặc tả ngôn ngữ Dart

Khi bạn sử dụng toán tử, bạn tạo biểu thức. Dưới đây là một số ví dụ về biểu thức toán tử

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
7

Trong , mỗi toán tử có mức độ ưu tiên cao hơn các toán tử trong các hàng theo sau nó. Ví dụ: toán tử nhân

int? lineCount;
assert(lineCount == null);
76 có mức độ ưu tiên cao hơn (và do đó thực thi trước) toán tử đẳng thức
String name = 'Bob';
58, có mức độ ưu tiên cao hơn toán tử logic AND
int? lineCount;
assert(lineCount == null);
95. Quyền ưu tiên đó có nghĩa là hai dòng mã sau thực thi theo cùng một cách

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
8

Cảnh báo. Đối với các toán tử nhận hai toán hạng, toán hạng ngoài cùng bên trái sẽ xác định phương thức nào được sử dụng. Ví dụ: nếu bạn có một đối tượng

int lineCount = 0;
11 và một đối tượng
int lineCount = 0;
12, thì
int lineCount = 0;
13 sử dụng phép cộng
int lineCount = 0;
11 (
String name = 'Bob';
59)

toán tử số học

Dart hỗ trợ các toán tử số học thông thường, như trong bảng sau

Toán tửÝ nghĩa_______58_______59Cộng
int? lineCount;
assert(lineCount == null);
79Trừ
int? lineCount;
assert(lineCount == null);
68Dấu trừ đơn vị hay còn gọi là phủ định (đảo dấu của biểu thức)
int? lineCount;
assert(lineCount == null);
74Nhân
int? lineCount;
assert(lineCount == null);
75Chia số
int? lineCount;
assert(lineCount == null);
77Chia hết, trả về kết quả là số nguyên
int? lineCount;
assert(lineCount == null);
76Lấy phần dư của một phép chia số nguyên (mô-đun)

Thí dụ

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
9

Dart cũng hỗ trợ cả toán tử tăng và giảm tiền tố và hậu tố

Toán tửÝ nghĩa
int lineCount = 0;
23
int lineCount = 0;
24 (giá trị biểu thức là
int lineCount = 0;
25)
int lineCount = 0;
26
int lineCount = 0;
24 (giá trị biểu thức là
int lineCount = 0;
28)
int lineCount = 0;
29
int lineCount = 0;
30 (giá trị biểu thức là
int lineCount = 0;
31)
int lineCount = 0;
32
int lineCount = 0;
30 (giá trị biểu thức là
int lineCount = 0;
28)

Thí dụ

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
0

Toán tử đẳng thức và quan hệ

Bảng sau liệt kê ý nghĩa của đẳng thức và toán tử quan hệ

Toán tửÝ nghĩa
String name = 'Bob';
58Bằng nhau;

Để kiểm tra xem hai đối tượng x và y có đại diện cho cùng một thứ hay không, hãy sử dụng toán tử

String name = 'Bob';
58. (Trong trường hợp hiếm hoi mà bạn cần biết liệu hai đối tượng có phải là cùng một đối tượng hay không, hãy sử dụng hàmgiống hệt() để thay thế. ) Đây là cách hoạt động của toán tử
String name = 'Bob';
58

  1. Nếu x hoặc y là null, trả về true nếu cả hai đều null và false nếu chỉ một giá trị null

  2. Trả về kết quả của việc gọi phương thức

    String name = 'Bob';
    58 trên x với đối số y. (Đúng vậy, các toán tử như
    String name = 'Bob';
    58 là các phương thức được gọi trên toán hạng đầu tiên của chúng. Để biết chi tiết, xem. )

Đây là một ví dụ về cách sử dụng từng toán tử đẳng thức và quan hệ

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
1

Người vận hành thử nghiệm loại

Các toán tử

Object name = 'Bob';
99,
Object name = 'Bob';
98 và
int? lineCount;
assert(lineCount == null);
92 rất hữu ích để kiểm tra các loại trong thời gian chạy

Toán tửÝ nghĩa
Object name = 'Bob';
99Typecast (cũng được sử dụng để chỉ định)_______1_______98True nếu đối tượng có loại được chỉ định
int? lineCount;
assert(lineCount == null);
92True nếu đối tượng không có loại được chỉ định

Kết quả của

int lineCount = 0;
51 là đúng nếu
int lineCount = 0;
52 triển khai giao diện được chỉ định bởi
int lineCount = 0;
53. Ví dụ:
int lineCount = 0;
54 luôn đúng

Sử dụng toán tử

Object name = 'Bob';
99 để chuyển một đối tượng sang một loại cụ thể khi và chỉ khi bạn chắc chắn rằng đối tượng thuộc loại đó. Thí dụ

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
2

Nếu bạn không chắc chắn rằng đối tượng thuộc loại

int lineCount = 0;
53, hãy sử dụng
int lineCount = 0;
57 để kiểm tra loại trước khi sử dụng đối tượng

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
3

Ghi chú. Mã không tương đương. Nếu

int lineCount = 0;
58 là null hoặc không phải là
int lineCount = 0;
59, thì ví dụ đầu tiên đưa ra một ngoại lệ;

Toán tử gán

Như bạn đã thấy, bạn có thể gán giá trị bằng cách sử dụng toán tử

int? lineCount;
assert(lineCount == null);
34. Để chỉ gán nếu biến được gán là null, hãy sử dụng toán tử
int lineCount = 0;
61

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
4

Các toán tử gán phức hợp như

int lineCount = 0;
04 kết hợp một phép toán với một phép gán

int? lineCount;
assert(lineCount == null);
34
int lineCount = 0;
02
int lineCount = 0;
65
int lineCount = 0;
66
int lineCount = 0;
07
int lineCount = 0;
04
int lineCount = 0;
03
int lineCount = 0;
70
int lineCount = 0;
06
int lineCount = 0;
72
int lineCount = 0;
05
int lineCount = 0;
74
int lineCount = 0;
75

Đây là cách các toán tử gán phức hợp hoạt động

Phép gán hợp chấtBiểu thức tương đươngCho toán tử op.
int lineCount = 0;
76
int lineCount = 0;
77Ví dụ.
int lineCount = 0;
78
int lineCount = 0;
79

Ví dụ sau sử dụng toán tử gán và gán phức hợp

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
5

Toán tử logic

Bạn có thể đảo ngược hoặc kết hợp các biểu thức boolean bằng các toán tử logic

Toán tửÝ nghĩa
int? lineCount;
assert(lineCount == null);
69đảo ngược biểu thức sau (thay đổi sai thành đúng và ngược lại)
int? lineCount;
assert(lineCount == null);
96logic OR
int? lineCount;
assert(lineCount == null);
95logic AND

Đây là một ví dụ về việc sử dụng các toán tử logic

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
6

Toán tử bitwise và shift

Bạn có thể thao tác từng bit số trong Dart. Thông thường, bạn sẽ sử dụng các toán tử dịch chuyển và bit này với các số nguyên

Toán tử Ý nghĩa_______58_______50AND
String name = 'Bob';
51OR
String name = 'Bob';
52XOR
int? lineCount;
assert(lineCount == null);
70Phần bù bit đơn vị (0 trở thành 1; 1 trở thành 0)
String name = 'Bob';
46Shift trái
String name = 'Bob';
47Shift phải
String name = 'Bob';
48Shift không dấu phải

Đây là một ví dụ về việc sử dụng toán tử bitwise và shift

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
7

ghi chú phiên bản. Toán tử

String name = 'Bob';
48 (được gọi là ca ba hoặc ca không dấu) yêu cầu ít nhất 2. 14

biểu thức điều kiện

Phi tiêu có hai toán tử cho phép bạn đánh giá chính xác các biểu thức có thể yêu cầu các câu lệnh

int lineCount = 0;
91Nếu điều kiện là đúng, đánh giá expr1 (và trả về giá trị của nó); .
int lineCount = 0;
92Nếu expr1 khác null, trả về giá trị của nó;

Khi bạn cần gán giá trị dựa trên biểu thức boolean, hãy cân nhắc sử dụng

Object name = 'Bob';
39 và
int lineCount = 0;
94

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
8

Nếu biểu thức boolean kiểm tra null, hãy cân nhắc sử dụng

int? lineCount;
assert(lineCount == null);
97

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
9

Ví dụ trước có thể được viết ít nhất theo hai cách khác, nhưng không ngắn gọn bằng

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
0

ký hiệu tầng

Cascades (

int? lineCount;
assert(lineCount == null);
99,
int lineCount = 0;
00) cho phép bạn thực hiện một chuỗi các thao tác trên cùng một đối tượng. Ngoài việc truy cập các thành viên cá thể, bạn cũng có thể gọi các phương thức cá thể trên cùng một đối tượng. Điều này thường giúp bạn tiết kiệm bước tạo một biến tạm thời và cho phép bạn viết mã linh hoạt hơn

Hãy xem xét đoạn mã sau

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
1

Hàm tạo,

int lineCount = 0;
98, trả về một đối tượng
int lineCount = 0;
99. Mã tuân theo ký hiệu xếp tầng hoạt động trên đối tượng này, bỏ qua mọi giá trị có thể được trả về

Ví dụ trước tương đương với mã này

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
2

Nếu đối tượng mà tầng hoạt động trên đó có thể là null, thì hãy sử dụng tầng rút ngắn null (

int lineCount = 0;
00) cho thao tác đầu tiên. Bắt đầu với
int lineCount = 0;
00 đảm bảo rằng không có hoạt động xếp tầng nào được thực hiện trên đối tượng null đó

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
3

ghi chú phiên bản. Cú pháp

int lineCount = 0;
00 yêu cầu ít nhất 2. 12

Mã trước tương đương với mã sau

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
4

Bạn cũng có thể lồng thác. Ví dụ

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
5

Hãy cẩn thận để xây dựng tầng của bạn trên một hàm trả về một đối tượng thực tế. Ví dụ: đoạn mã sau không thành công

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
6

Cuộc gọi

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
03 trả về giá trị vô hiệu và bạn không thể tạo tầng trên
Object name = 'Bob';
15

Ghi chú. Nói một cách chính xác, ký hiệu “dấu chấm kép” cho các tầng không phải là toán tử. Nó chỉ là một phần của cú pháp Dart

nhà khai thác khác

Bạn đã thấy hầu hết các toán tử còn lại trong các ví dụ khác

OperatorNameÝ nghĩa
int? lineCount;
assert(lineCount == null);
62Ứng dụng chức năngĐại diện cho một cuộc gọi chức năng
String name = 'Bob';
67Truy cập đăng kýĐại diện cho một cuộc gọi đến nhà điều hành
String name = 'Bob';
67 có thể ghi đè; .
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
08 chuyển int
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
09 đến
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
10 để truy cập phần tử tại chỉ mục
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
09
int? lineCount;
assert(lineCount == null);
64Truy cập chỉ số con có điều kiệnGiống như
String name = 'Bob';
67, nhưng toán hạng ngoài cùng bên trái có thể là null; .
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
14 chuyển int
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
09 đến
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
10 để truy cập phần tử tại chỉ mục
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
09 trừ khi
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
10 là null (trong trường hợp đó biểu thức ước tính là null)_______61_______65Truy cập thành viên Đề cập đến một thuộc tính của một biểu thức; .
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
20 chọn thuộc tính
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
21 từ biểu thức
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
22_______61_______66Truy cập thành viên có điều kiệnGiống như
int? lineCount;
assert(lineCount == null);
65, nhưng toán hạng ngoài cùng bên trái có thể là null; .
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
25 chọn thuộc tính
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
21 từ biểu thức
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
22 trừ khi
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
22 là null (trong trường hợp đó, giá trị của
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
25 là null)
Object name = 'Bob';
43Null assertion operatorTruyền một biểu thức sang loại không thể null cơ bản của nó, đưa ra một ngoại lệ thời gian chạy nếu truyền không thành công; .
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
31 khẳng định
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
22 không phải là null và chọn thuộc tính
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
21, trừ khi
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
22 là null trong trường hợp đó, một ngoại lệ thời gian chạy được đưa ra

Để biết thêm thông tin về các toán tử

int? lineCount;
assert(lineCount == null);
65,
int? lineCount;
assert(lineCount == null);
66 và
int? lineCount;
assert(lineCount == null);
99, hãy xem

Báo cáo luồng điều khiển

Bạn có thể kiểm soát luồng mã Dart của mình bằng cách sử dụng bất kỳ cách nào sau đây

  • String name = 'Bob';
    00 và
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    39
  • String name = 'Bob';
    79 vòng lặp
  • Vòng lặp
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    41 và
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    42-
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    41
  • int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    44 và
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    45
  • int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    46 và
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    47
  • int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    48

Bạn cũng có thể tác động đến luồng điều khiển bằng cách sử dụng

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
49 và
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
50, như được giải thích trong

Nếu và khác

Dart hỗ trợ

String name = 'Bob';
00 câu lệnh với tùy chọn
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
39 câu lệnh, như mẫu tiếp theo cho thấy. Cũng thấy

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
7

Các điều kiện câu lệnh phải là các biểu thức đánh giá các giá trị boolean, không có gì khác. Xem để biết thêm thông tin

Đối với vòng lặp

Bạn có thể lặp với vòng lặp

String name = 'Bob';
79 tiêu chuẩn. Ví dụ

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
8

Các lần đóng bên trong các vòng lặp

String name = 'Bob';
79 của Dart ghi lại giá trị của chỉ mục, tránh một cạm bẫy phổ biến được tìm thấy trong JavaScript. Ví dụ, xem xét

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
9

Đầu ra là

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
55 và sau đó là
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
09, như mong đợi. Ngược lại, ví dụ sẽ in
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
57 và sau đó là
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
57 trong JavaScript

Nếu đối tượng mà bạn đang lặp lại là một Có thể lặp lại (chẳng hạn như Danh sách hoặc Bộ) và nếu bạn không cần biết bộ đếm lặp lại hiện tại, bạn có thể sử dụng biểu mẫu

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
59 của

var name = 'Bob';
00

Mẹo. Để thực hành sử dụng

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
59, hãy làm theo phòng thí nghiệm codelab bộ sưu tập Iterable

Các lớp có thể lặp lại cũng có một phương thức forEach() như một tùy chọn khác

var name = 'Bob';
01

Trong khi và làm trong khi

Vòng lặp

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
41 đánh giá điều kiện trước vòng lặp

var name = 'Bob';
02

Vòng lặp

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
42-
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
41 đánh giá điều kiện sau vòng lặp

var name = 'Bob';
03

Phá vỡ và tiếp tục

Sử dụng

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
44 để dừng vòng lặp

var name = 'Bob';
04

Sử dụng

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
45 để chuyển sang vòng lặp tiếp theo

var name = 'Bob';
05

Bạn có thể viết ví dụ đó theo cách khác nếu bạn đang sử dụng một

String name = 'Bob';
26 chẳng hạn như danh sách hoặc tập hợp

var name = 'Bob';
06

Chuyển đổi và trường hợp

Chuyển câu lệnh trong Dart so sánh các hằng số nguyên, chuỗi hoặc thời gian biên dịch bằng cách sử dụng

String name = 'Bob';
58. Tất cả các đối tượng được so sánh phải là các thể hiện của cùng một lớp (và không thuộc bất kỳ kiểu con nào của nó) và lớp không được ghi đè lên
String name = 'Bob';
58. hoạt động tốt trong các câu lệnh
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
46

Mỗi mệnh đề

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
47 không trống kết thúc bằng câu lệnh
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
44, theo quy định. Các cách hợp lệ khác để kết thúc mệnh đề
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
47 không trống là câu lệnh
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
45,
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
50 hoặc
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
75

Sử dụng mệnh đề

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
76 để thực thi mã khi không có mệnh đề
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
47 khớp

var name = 'Bob';
07

Ví dụ sau bỏ qua câu lệnh

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
44 trong mệnh đề
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
47, do đó tạo ra lỗi

var name = 'Bob';
08

Tuy nhiên, Dart hỗ trợ các mệnh đề

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
47 trống rỗng, cho phép một hình thức rút gọn

var name = 'Bob';
09

Nếu bạn thực sự muốn bỏ qua, bạn có thể sử dụng câu lệnh

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
45 và nhãn

var name = 'Bob';
10

Mệnh đề

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
47 có thể có các biến cục bộ, chỉ hiển thị bên trong phạm vi của mệnh đề đó

khẳng định

Trong quá trình phát triển, hãy sử dụng câu lệnh khẳng định—______67_______83;—để phá vỡ quá trình thực thi bình thường nếu điều kiện boolean là sai. Bạn có thể tìm thấy các ví dụ về tuyên bố khẳng định trong chuyến tham quan này. Dưới đây là một số chi tiết

var name = 'Bob';
11

Để đính kèm một thông báo vào một xác nhận, hãy thêm một chuỗi làm đối số thứ hai vào

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
48 (tùy chọn với một )

var name = 'Bob';
12

Đối số đầu tiên của

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
48 có thể là bất kỳ biểu thức nào phân giải thành giá trị boolean. Nếu giá trị của biểu thức là đúng, xác nhận thành công và quá trình thực thi tiếp tục. Nếu nó sai, khẳng định không thành công và một ngoại lệ (một
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
86) được đưa ra

Khi nào xác nhận chính xác hoạt động?

  • Flutter cho phép xác nhận trong
  • Các công cụ chỉ dành cho phát triển như [_______67_______87][] thường bật xác nhận theo mặc định
  • Some tools, such as
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    88 and [
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    89][] support assertions through a command-line flag.
    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    90

Trong mã sản xuất, các xác nhận bị bỏ qua và các đối số của

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
48 không được đánh giá

ngoại lệ

Mã phi tiêu của bạn có thể ném và bắt ngoại lệ. Ngoại lệ là lỗi cho biết có điều gì đó không mong muốn đã xảy ra. Nếu ngoại lệ không bị bắt, thì ngoại lệ đã đưa ra sẽ bị tạm dừng và thường thì cô lập và chương trình của nó bị chấm dứt

Trái ngược với Java, tất cả các ngoại lệ của Dart đều là ngoại lệ không được kiểm tra. Các phương thức không khai báo những ngoại lệ mà chúng có thể ném ra và bạn không bắt buộc phải bắt bất kỳ ngoại lệ nào

Phi tiêu cung cấp các loại

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
92 và
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
93, cũng như nhiều loại phụ được xác định trước. Tất nhiên, bạn có thể xác định các ngoại lệ của riêng mình. Tuy nhiên, các chương trình Dart có thể ném bất kỳ đối tượng không null nào—không chỉ các đối tượng Ngoại lệ và Lỗi—như một ngoại lệ

Ném

Đây là một ví dụ về ném hoặc nâng cao, một ngoại lệ

var name = 'Bob';
13

Bạn cũng có thể ném các đối tượng tùy ý

var name = 'Bob';
14

Ghi chú. Mã chất lượng sản xuất thường đưa ra các loại triển khai

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
93 hoặc
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
92

Vì ném ngoại lệ là một biểu thức nên bạn có thể ném ngoại lệ vào câu lệnh => cũng như bất kỳ nơi nào khác cho phép biểu thức

var name = 'Bob';
15

Bắt lấy

Bắt hoặc chụp, một ngoại lệ ngăn ngoại lệ lan truyền (trừ khi bạn vẽ lại ngoại lệ). Bắt một ngoại lệ cho bạn cơ hội để xử lý nó

var name = 'Bob';
16

Để xử lý mã có thể ném nhiều loại ngoại lệ, bạn có thể chỉ định nhiều mệnh đề bắt. Mệnh đề bắt đầu tiên khớp với loại đối tượng bị ném sẽ xử lý ngoại lệ. Nếu mệnh đề catch không chỉ định một loại, thì mệnh đề đó có thể xử lý bất kỳ loại đối tượng bị ném nào

var name = 'Bob';
17

Như đoạn mã trước cho thấy, bạn có thể sử dụng

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
96 hoặc
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
97 hoặc cả hai. Sử dụng
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
96 khi bạn cần chỉ định loại ngoại lệ. Sử dụng
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
97 khi trình xử lý ngoại lệ của bạn cần đối tượng ngoại lệ

Bạn có thể chỉ định một hoặc hai tham số cho

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
00. Đầu tiên là ngoại lệ đã được ném và thứ hai là dấu vết ngăn xếp (đối tượng
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
01)

var name = 'Bob';
18

Để xử lý một phần ngoại lệ, đồng thời cho phép nó lan truyền, hãy sử dụng từ khóa

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
02

var name = 'Bob';
19

Cuối cùng

Để đảm bảo rằng một số mã chạy cho dù có ném ngoại lệ hay không, hãy sử dụng mệnh đề

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
03. Nếu không có mệnh đề
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
97 khớp với ngoại lệ, thì ngoại lệ sẽ được lan truyền sau khi mệnh đề
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
03 chạy

var name = 'Bob';
20

Mệnh đề

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
03 chạy sau bất kỳ mệnh đề
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
97 phù hợp nào

var name = 'Bob';
21

Tìm hiểu thêm bằng cách đọc phần tham quan thư viện

Các lớp học

Dart là một ngôn ngữ hướng đối tượng với các lớp và kế thừa dựa trên mixin. Mỗi đối tượng là một thể hiện của một lớp và tất cả các lớp ngoại trừ

String name = 'Bob';
17 đều giảm dần từ
Object name = 'Bob';
35. Kế thừa dựa trên mixin có nghĩa là mặc dù mọi lớp (ngoại trừ ,
Object name = 'Bob';
45) có chính xác một lớp cha, nhưng phần thân của lớp có thể được sử dụng lại trong nhiều hệ thống phân cấp lớp. là một cách để thêm chức năng vào một lớp mà không cần thay đổi lớp hoặc tạo một lớp con

Sử dụng các thành viên lớp

Các đối tượng có các thành viên bao gồm các hàm và dữ liệu (tương ứng là các phương thức và biến thể hiện). Khi bạn gọi một phương thức, bạn gọi nó trên một đối tượng. phương thức có quyền truy cập vào các chức năng và dữ liệu của đối tượng đó

Sử dụng dấu chấm (

int? lineCount;
assert(lineCount == null);
65) để chỉ một biến thể hiện hoặc một phương thức

var name = 'Bob';
22

Sử dụng

int? lineCount;
assert(lineCount == null);
66 thay vì
int? lineCount;
assert(lineCount == null);
65 để tránh ngoại lệ khi toán hạng ngoài cùng bên trái là null

var name = 'Bob';
23

Sử dụng hàm tạo

You can create an object using a constructor. Constructor names can be either

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
14 or
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
15. For example, the following code creates
int lineCount = 0;
12 objects using the
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
17 and
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
18 constructors

var name = 'Bob';
24

The following code has the same effect, but uses the optional

int? lineCount;
assert(lineCount == null);
07 keyword before the constructor name

var name = 'Bob';
25

Some classes provide . To create a compile-time constant using a constant constructor, put the

Object name = 'Bob';
84 keyword before the constructor name

var name = 'Bob';
26

Constructing two identical compile-time constants results in a single, canonical instance

var name = 'Bob';
27

Within a constant context, you can omit the

Object name = 'Bob';
84 before a constructor or literal. For example, look at this code, which creates a const map

var name = 'Bob';
28

You can omit all but the first use of the

Object name = 'Bob';
84 keyword

var name = 'Bob';
29

If a constant constructor is outside of a constant context and is invoked without

Object name = 'Bob';
84, it creates a non-constant object

var name = 'Bob';
30

Getting an object’s type

To get an object’s type at runtime, you can use the

Object name = 'Bob';
35 property
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
25, which returns a
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
26 object

var name = 'Bob';
31

Use a rather than

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
25 to test an object’s type. In production environments, the test
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
28 is more stable than the test
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
29

Up to here, you’ve seen how to use classes. The rest of this section shows how to implement classes

Instance variables

Here’s how you declare instance variables

var name = 'Bob';
32

All uninitialized instance variables have the value

Object name = 'Bob';
33

All instance variables generate an implicit getter method. Non-final instance variables and

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
31 instance variables without initializers also generate an implicit setter method. For details, see

If you initialize a non-

Object name = 'Bob';
76 instance variable where it’s declared, the value is set when the instance is created, which is before the constructor and its initializer list execute

var name = 'Bob';
33

Instance variables can be

Object name = 'Bob';
83, in which case they must be set exactly once. Initialize
Object name = 'Bob';
83, non-
Object name = 'Bob';
76 instance variables at declaration, using a constructor parameter, or using a constructor’s

var name = 'Bob';
34

If you need to assign the value of a

Object name = 'Bob';
83 instance variable after the constructor body starts, you can use one of the following

  • Use a
  • Use
    late String description;
    
    void main() {
      description = 'Feijoada!';
      print(description);
    }
    31, but a
    late String description;
    
    void main() {
      description = 'Feijoada!';
      print(description);
    }
    31 without an initializer adds a setter to the API

Constructors

Declare a constructor by creating a function with the same name as its class (plus, optionally, an additional identifier as described in ). The most common form of constructor, the generative constructor, creates a new instance of a class

var name = 'Bob';
35

The

Object name = 'Bob';
80 keyword refers to the current instance

Note. Use

Object name = 'Bob';
80 only when there is a name conflict. Otherwise, Dart style omits the
Object name = 'Bob';
80

Initializing formal parameters

The pattern of assigning a constructor argument to an instance variable is so common, Dart has initializing formal parameters to make it easy

Initializing parameters can also be used to initialize non-nullable or

Object name = 'Bob';
83 instance variables, which both must be initialized or provided a default value

var name = 'Bob';
36

The variables introduced by the initializing formals are implicitly final and only in scope of the initializer list

Default constructors

If you 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 superclass

Constructors aren’t inherited

Subclasses don’t inherit constructors from their superclass. A subclass that declares no constructors has only the default (no argument, no name) constructor

Named constructors

Use a named constructor to implement multiple constructors for a class or to provide extra clarity

var name = 'Bob';
37

Remember that constructors are not inherited, which means that a superclass’s named constructor is not inherited by a subclass. If you want a subclass to be created with a named constructor defined in the 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’s unnamed, no-argument constructor. The superclass’s constructor is called at the beginning of the constructor body. If an is also being used, it executes before the superclass is called. In summary, the order of execution is as follows

  1. initializer list
  2. superclass’s no-arg constructor
  3. main class’s no-arg constructor

If the superclass doesn’t have an unnamed, no-argument constructor, then you must manually call one of the constructors in the superclass. Specify the superclass constructor after a colon (

int lineCount = 0;
94), just before the constructor body (if any)

In the following example, the constructor for the Employee class calls the named constructor for its superclass, Person. Click Run to execute the code

var name = 'Bob';
38

Because the arguments to the superclass constructor are evaluated before invoking the constructor, an argument can be an expression such as a function call

var name = 'Bob';
39

Warning. Arguments to the superclass constructor don’t have access to

Object name = 'Bob';
80. For example, arguments can call static methods but not instance methods

To avoid having to manually pass each parameter into the super invocation of a constructor, you can use super-initializer parameters to forward parameters to the specified or default superclass constructor. This feature can’t be used with redirecting constructors. Super-initializer parameters have similar syntax and semantics to

var name = 'Bob';
40

Super-initializer parameters cannot be positional if the super-constructor invocation already has positional arguments, but they can always be named

var name = 'Bob';
41

Version note. Using super-initializer parameters requires a of at least 2. 17. If you’re using an earlier language version, you must manually pass in all super constructor parameters

Initializer list

Besides invoking a superclass constructor, you can also initialize instance variables before the constructor body runs. Separate initializers with commas

var name = 'Bob';
42

Warning. The right-hand side of an initializer doesn’t have access to

Object name = 'Bob';
80

During development, you can validate inputs by using

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
48 in the initializer list

var name = 'Bob';
43

Initializer lists are handy when setting up final fields. The following example initializes three final fields in an initializer list. Click Run to execute the code

var name = 'Bob';
44

Redirecting constructors

Sometimes a constructor’s only purpose is to redirect to another constructor in the same class. A redirecting constructor’s body is empty, with the constructor call (using

Object name = 'Bob';
80 instead of the class name) appearing after a colon (. )

var name = 'Bob';
45

Constant constructors

If your class produces objects that never change, you can make these objects compile-time constants. To do this, define a

Object name = 'Bob';
84 constructor and make sure that all instance variables are
Object name = 'Bob';
83

var name = 'Bob';
46

Constant constructors don’t always create constants. For details, see the section on

Factory constructors

Use the

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
50 keyword when implementing a constructor that doesn’t always create a new instance of its class. For example, a factory constructor might return an instance from a cache, or it might return an instance of a subtype. Another use case for factory constructors is initializing a final variable using logic that can’t be handled in the initializer list

Tip. Another way to handle late initialization of a final variable is to

In the following example, the

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
52 factory constructor returns objects from a cache, and the
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
53 factory constructor initializes a final variable from a JSON object

var name = 'Bob';
47

Ghi chú. Các nhà xây dựng nhà máy không có quyền truy cập vào

Object name = 'Bob';
80

Gọi một nhà xây dựng nhà máy giống như bất kỳ nhà xây dựng nào khác

var name = 'Bob';
48

phương pháp

Phương thức là các chức năng cung cấp hành vi cho một đối tượng

Phương thức sơ thẩm

Các phương thức thể hiện trên các đối tượng có thể truy cập các biến thể hiện và

Object name = 'Bob';
80. Phương thức
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
56 trong mẫu sau đây là một ví dụ về phương thức thể hiện

var name = 'Bob';
49

nhà điều hành

Toán tử là các phương thức cá thể có tên đặc biệt. Phi tiêu cho phép bạn xác định toán tử với các tên sau

int? lineCount;
assert(lineCount == null);
89
String name = 'Bob';
59
String name = 'Bob';
51
String name = 'Bob';
48
int? lineCount;
assert(lineCount == null);
87
int? lineCount;
assert(lineCount == null);
75
String name = 'Bob';
52
String name = 'Bob';
67
int? lineCount;
assert(lineCount == null);
88
int? lineCount;
assert(lineCount == null);
77
String name = 'Bob';
50
int? lineCount;
assert(lineCount == null);
08
int? lineCount;
assert(lineCount == null);
86
int? lineCount;
assert(lineCount == null);
74
String name = 'Bob';
46
String name = 'Bob';
49
int? lineCount;
assert(lineCount == null);
79
int? lineCount;
assert(lineCount == null);
76
String name = 'Bob';
47
String name = 'Bob';
58

Ghi chú. You may have noticed that some , like

int? lineCount;
assert(lineCount == null);
94, aren’t in the list of names. That’s because they’re just syntactic sugar. For example, the expression
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
78 is syntactic sugar for
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
79

An operator declaration is identified using the built-in identifier

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
80. The following example defines vector addition (
String name = 'Bob';
59), subtraction (
int? lineCount;
assert(lineCount == null);
79), and equality (
String name = 'Bob';
58)

var name = 'Bob';
50

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

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
84 and
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
85 keywords

var name = 'Bob';
51

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 calls the getter exactly once, saving its value in a temporary variable

Abstract methods

Instance, getter, and setter methods can be abstract, defining an interface but leaving its implementation up to other classes. Abstract methods can only exist in

To make a method abstract, use a semicolon (;) instead of a method body

var name = 'Bob';
52

Abstract classes

Use the

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
86 modifier to define an abstract class—a class that can’t be instantiated. Abstract classes are useful for defining interfaces, often with some implementation. If you want your abstract class to appear to be instantiable, define a

Abstract classes often have . Here’s an example of declaring an abstract class that has an abstract method

var name = 'Bob';
53

Implicit interfaces

Every class implicitly defines an interface containing all the instance members of the class and of any interfaces it implements. If you want to create a class A that supports class B’s API without inheriting B’s implementation, class A should implement the B interface

A class implements one or more interfaces by declaring them in an

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
87 clause and then providing the APIs required by the interfaces. For example

var name = 'Bob';
54

Here’s an example of specifying that a class implements multiple interfaces

var name = 'Bob';
55

Extending a class

Use

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
88 to create a subclass, and
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
89 to refer to the superclass

var name = 'Bob';
56

For another usage of

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
88, see the discussion of in

Overriding members

Subclasses can override instance methods (including ), getters, and setters. You can use the

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
91 annotation to indicate that you are intentionally overriding a member

var name = 'Bob';
57

An overriding method declaration must match the method (or methods) that it overrides in several ways

  • The return type must be the same type as (or a subtype of) the overridden method’s return type
  • Argument types must be the same type as (or a supertype of) the overridden method’s argument types. In the preceding example, the
    late String description;
    
    void main() {
      description = 'Feijoada!';
      print(description);
    }
    92 setter of
    late String description;
    
    void main() {
      description = 'Feijoada!';
      print(description);
    }
    93 changes the argument type from
    Object name = 'Bob';
    19 to a supertype,
    String name = 'Bob';
    40
  • If the overridden method accepts n positional parameters, then the overriding method must also accept n positional parameters
  • A can’t override a non-generic one, and a non-generic method can’t override a generic one

Sometimes you might want to narrow the type of a method parameter or an instance variable. This violates the normal rules, and it’s similar to a downcast in that it can cause a type error at runtime. Still, narrowing the type is possible if the code can guarantee that a type error won’t occur. In this case, you can use the in a parameter declaration. For details, see the Dart language specification

Warning. If you override

String name = 'Bob';
58, you should also override Object’s
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
98 getter. For an example of overriding
String name = 'Bob';
58 and
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
98, see

noSuchMethod()

To detect or react whenever code attempts to use a non-existent method or instance variable, you can override

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
01

var name = 'Bob';
58

You can’t invoke an unimplemented method unless one of the following is true

  • The receiver has the static type

    Object name = 'Bob';
    47

  • The receiver has a static type that defines the unimplemented method (abstract is OK), and the dynamic type of the receiver has an implementation of

    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    01 that’s different from the one in class
    Object name = 'Bob';
    35

For more information, see the informal noSuchMethod forwarding specification

Extension methods

Extension methods are a way to add functionality to existing libraries. You might use extension methods without even knowing it. For example, when you use code completion in an IDE, it suggests extension methods alongside regular methods

Here’s an example of using an extension method on

Object name = 'Bob';
20 named
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
06 that’s defined in
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
07

var name = 'Bob';
59

For details of using and implementing extension methods, see the extension methods page

Enumerated types

Enumerated types, often called enumerations or enums, are a special kind of class used to represent a fixed number of constant values

Note. All enums automatically extend the

String name = 'Bob';
23 class. They are also sealed, meaning they cannot be subclassed, implemented, mixed in, or otherwise explicitly instantiated

Abstract classes and mixins can explicitly implement or extend

String name = 'Bob';
23, but unless they are then implemented by or mixed into an enum declaration, no objects can actually implement the type of that class or mixin

Declaring simple enums

To declare a simple enumerated type, use the

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
10 keyword and list the values you want to be enumerated

var name = 'Bob';
60

Tip. You can also use when declaring an enumerated type to help prevent copy-paste errors

Declaring enhanced enums

Dart also allows enum declarations to declare classes with fields, methods, and const constructors which are limited to a fixed number of known constant instances

To declare an enhanced enum, follow a syntax similar to normal , but with a few extra requirements

  • Instance variables must be
    Object name = 'Bob';
    83, including those added by
  • All must be constant
  • can only return one of the fixed, known enum instances
  • No other class can be extended as
    String name = 'Bob';
    23 is automatically extended
  • There cannot be overrides for
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    13,
    late String description;
    
    void main() {
      description = 'Feijoada!';
      print(description);
    }
    98, the equality operator
    String name = 'Bob';
    58
  • A member named
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    16 cannot be declared in an enum, as it would conflict with the automatically generated static
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    16 getter
  • All instances of the enum must be declared in the beginning of the declaration, and there must be at least one instance declared

Here is an example that declares an enhanced enum with multiple instances, instance variables, a getter, and an implemented interface

var name = 'Bob';
61

To learn more about declaring enhanced enums, see the section on

Version note. Enhanced enums require a of at least 2. 17

Using enums

Access the enumerated values like any other

var name = 'Bob';
62

Each value in an enum has an

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
13 getter, which returns the zero-based position of the value in the enum declaration. For example, the first value has index 0, and the second value has index 1

var name = 'Bob';
63

To get a list of all the enumerated values, use the enum’s

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
16 constant

var name = 'Bob';
64

You can use enums in , and you’ll get a warning if you don’t handle all of the enum’s values

var name = 'Bob';
65

If you need to access the name of an enumerated value, such as

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
20 from
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
21, use the
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
22 property

var name = 'Bob';
66

Thêm các tính năng cho một lớp. hỗn hợp

Mixin là một cách sử dụng lại mã của một lớp trong nhiều hệ thống phân cấp lớp

Để sử dụng mixin, hãy sử dụng từ khóa

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
23 theo sau là một hoặc nhiều tên mixin. Ví dụ sau đây cho thấy hai lớp sử dụng mixins

var name = 'Bob';
67

To implement a mixin, create a class that extends Object and declares no constructors. Unless you want your mixin to be usable as a regular class, use the

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
24 keyword instead of
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
25. For example

var name = 'Bob';
68

Sometimes you might want to restrict the types that can use a mixin. For example, the mixin might depend on being able to invoke a method that the mixin doesn’t define. As the following example shows, you can restrict a mixin’s use by using the

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
96 keyword to specify the required superclass

var name = 'Bob';
69

In the preceding code, only classes that extend or implement the

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
27 class can use the mixin
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
28. Because
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
29 extends
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
27,
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
29 can mix in
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
28

Class variables and methods

Use the

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
33 keyword to implement class-wide variables and methods

Static variables

Static variables (class variables) are useful for class-wide state and constants

var name = 'Bob';
70

Static variables aren’t initialized until they’re used

Note. This page follows the of preferring

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
34 for constant names

Static methods

Static methods (class methods) don’t operate on an instance, and thus don’t have access to

Object name = 'Bob';
80. They do, however, have access to static variables. As the following example shows, you invoke static methods directly on a class

var name = 'Bob';
71

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 pass a static method as a parameter to a constant constructor

Generics

If you look at the API documentation for the basic array type,

Object name = 'Bob';
21, you’ll see that the type is actually
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
37. The <…> notation marks List as a generic (or parameterized) type—a type that has formal type parameters. , most type variables have single-letter names, such as E, T, S, K, and V.

Why use generics?

Generics are often required for type safety, but they have more benefits than just allowing your code to run

  • Properly specifying generic types results in better generated code
  • You can use generics to reduce code duplication

If you intend for a list to contain only strings, you can declare it as

int? lineCount;
assert(lineCount == null);
46 (read that as “list of string”). That way you, your fellow programmers, and your tools can detect that assigning a non-string to the list is probably a mistake. Here’s an example

var name = 'Bob';
72

Another reason for using generics is to reduce code duplication. Generics let you share a single interface and implementation between many types, while still taking advantage of static analysis. For example, say you create an interface for caching an object

var name = 'Bob';
73

You discover that you want a string-specific version of this interface, so you create another interface

var name = 'Bob';
74

Later, you decide you want a number-specific version of this interface… You get the idea

Generic types can save you the trouble of creating all these interfaces. Instead, you can create a single interface that takes a type parameter

var name = 'Bob';
75

In this code, T is the stand-in type. It’s a placeholder that you can think of as a type that a developer will define later

Using collection literals

List, set, and map literals can be parameterized. Parameterized literals are just like the literals you’ve already seen, except that you add

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
39 (for lists and sets) or
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
40 (for maps) before the opening bracket. Here is an example of using typed literals

var name = 'Bob';
76

Using parameterized types with constructors

To specify one or more types when using a constructor, put the types in angle brackets (

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
41) just after the class name. For example

var name = 'Bob';
77

Đoạn mã sau tạo một bản đồ có các khóa và giá trị số nguyên thuộc loại Chế độ xem

var name = 'Bob';
78

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 a collection

var name = 'Bob';
79

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 is a List, but you can’t test whether it’s a

int? lineCount;
assert(lineCount == null);
46

Restricting the parameterized type

When implementing a generic type, you might want to limit the types that can be provided as arguments, so that the argument must be a subtype of a particular type. You can do this using

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
88

A common use case is ensuring that a type is non-nullable by making it a subtype of

Object name = 'Bob';
35 (instead of the default, )

var name = 'Bob';
80

You can use

late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
88 with other types besides
Object name = 'Bob';
35. Here’s an example of extending
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
48, so that members of
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
48 can be called on objects of type
int lineCount = 0;
53

var name = 'Bob';
81

It’s OK to use

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
48 or any of its subtypes as the generic argument

var name = 'Bob';
82

It’s also OK to specify no generic argument

var name = 'Bob';
83

Specifying any non-

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
48 type results in an error

var name = 'Bob';
84

Using generic methods

Methods and functions also allow type arguments

var name = 'Bob';
85

Here the generic type parameter on

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
53 (
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
54) allows you to use the type argument
int lineCount = 0;
53 in several places

  • In the function’s return type (
    int lineCount = 0;
    53)
  • In the type of an argument (
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    57)
  • In the type of a local variable (
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    58)

Libraries and visibility

The

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
59 and
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
60 directives can help you create a modular and shareable code base. Libraries not only provide APIs, but are a unit of privacy. identifiers that start with an underscore (
Object name = 'Bob';
54) are visible only inside the library. Every Dart app is a library, even if it doesn’t use a
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
60 directive

Libraries can be distributed using packages

Nếu bạn muốn biết tại sao Dart lại sử dụng dấu gạch dưới thay vì các từ khóa bổ trợ truy cập như

Object name = 'Bob';
51 hoặc
Object name = 'Bob';
53, hãy xem vấn đề về SDK 33383

Using libraries

Use

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
59 to specify how a namespace from one library is used in the scope of another library

For example, Dart web apps generally use the dart. html library, which they can import like this

var name = 'Bob';
86

The only required argument to

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
59 is a URI specifying the library. For built-in libraries, the URI has the special
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
67 scheme. For other libraries, you can use a file system path or the
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
68 scheme. The
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
68 scheme specifies libraries provided by a package manager such as the pub tool. Ví dụ

var name = 'Bob';
87

Note. URI stands for uniform resource identifier. URLs (uniform resource locators) are a common kind of URI

Specifying a library prefix

If you import two libraries that have conflicting identifiers, then you can specify a prefix for one or both libraries. For example, if library1 and library2 both have an Element class, then you might have code like this

var name = 'Bob';
88

Importing only part of a library

If you want to use only part of a library, you can selectively import the library. For example

var name = 'Bob';
89

Lazily loading a library

Deferred loading (also called lazy loading) allows a web app to load a library on demand, if and when the library is needed. Here are some cases when you might use deferred loading

  • To reduce a web app’s initial startup time
  • To perform A/B testing—trying out alternative implementations of an algorithm, for example
  • To load rarely used functionality, such as optional screens and dialogs

Only

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
89 supports deferred loading. Flutter and the Dart VM don’t support deferred loading. To learn more, see issue #33118 and issue #27776

To lazily load a library, you must first import it using

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
71

var name = 'Bob';
90

When you need the library, invoke

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
72 using the library’s identifier

var name = 'Bob';
91

In the preceding code, the

Object name = 'Bob';
59 keyword pauses execution until the library is loaded. For more information about
Object name = 'Bob';
61 and
Object name = 'Bob';
59, see

You can invoke

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
72 multiple times on a library without problems. The library is loaded only once

Keep in mind the following when you use deferred loading

  • A deferred library’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 in the importing file. Instead, consider moving interface types to a library imported by both the deferred library and the importing file
  • Dart implicitly inserts
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    72 into the namespace that you define using
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    78. The
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    72 function returns a

Implementing libraries

See Create Library Packages for advice on how to implement a library package, including

  • How to organize library source code
  • How to use the
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    81 directive
  • When to use the
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    82 directive
  • When to use the
    // This is the program's only call to readThermometer().
    late String temperature = readThermometer(); // Lazily initialized.
    60 directive
  • How to use conditional imports and exports to implement a library that supports multiple platforms

Asynchrony support

Dart libraries are full of functions that return

String name = 'Bob';
24 or
String name = 'Bob';
25 objects. These functions are asynchronous. they return after setting up a possibly time-consuming operation (such as I/O), without waiting for that operation to complete

The

Object name = 'Bob';
61 and
Object name = 'Bob';
59 keywords support asynchronous programming, letting you write asynchronous code that looks similar to synchronous code

Handling Futures

When you need the result of a completed Future, you have two options

  • Use
    Object name = 'Bob';
    61 and
    Object name = 'Bob';
    59, as described here and in the asynchronous programming codelab
  • Use the Future API, as described

Code that uses

Object name = 'Bob';
61 and
Object name = 'Bob';
59 is asynchronous, but it looks a lot like synchronous code. For example, here’s some code that uses
Object name = 'Bob';
59 to wait for the result of an asynchronous function

var name = 'Bob';
92

To use

Object name = 'Bob';
59, code must be in an
Object name = 'Bob';
61 function—a function marked as
Object name = 'Bob';
61

var name = 'Bob';
93

Note. Although an

Object name = 'Bob';
61 function might perform time-consuming operations, it doesn’t wait for those operations. Instead, the
Object name = 'Bob';
61 function executes only until it encounters its first
Object name = 'Bob';
59 expression. Then it returns a
String name = 'Bob';
24 object, resuming execution only after the
Object name = 'Bob';
59 expression completes

Use

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
01,
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
97, and
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
03 to handle errors and cleanup in code that uses
Object name = 'Bob';
59

var name = 'Bob';
94

You can use

Object name = 'Bob';
59 multiple times in an
Object name = 'Bob';
61 function. For example, the following code waits three times for the results of functions

var name = 'Bob';
95

In

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
07, the value of
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
08 is usually a Future; if it isn’t, then the value is automatically wrapped in a Future. This Future object indicates a promise to return an object. The value of
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
07 is that returned object. The await expression makes execution pause until that object is available

If you get a compile-time error when using

Object name = 'Bob';
59, make sure
Object name = 'Bob';
59 is in an
Object name = 'Bob';
61 function. For example, to use
Object name = 'Bob';
59 in your app’s
Object name = 'Bob';
17 function, the body of
Object name = 'Bob';
17 must be marked as
Object name = 'Bob';
61

var name = 'Bob';
96

Note. The preceding example uses an

Object name = 'Bob';
61 function (
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
18) without waiting for a result—a practice that can cause problems if the code assumes that the function has finished executing. To avoid this problem, use the

For an interactive introduction to using futures,

Object name = 'Bob';
61, and
Object name = 'Bob';
59, see the asynchronous programming codelab

Declaring async functions

An

Object name = 'Bob';
61 function is a function whose body is marked with the
Object name = 'Bob';
61 modifier

Adding the

Object name = 'Bob';
61 keyword to a function makes it return a Future. For example, consider this synchronous function, which returns a String

var name = 'Bob';
97

If you change it to be an

Object name = 'Bob';
61 function—for example, because a future implementation will be time consuming—the returned value is a Future

var name = 'Bob';
98

Note that the function’s body doesn’t need to use the Future API. Dart creates the Future object if necessary. If your function doesn’t return a useful value, make its return type

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
25

For an interactive introduction to using futures,

Object name = 'Bob';
61, and
Object name = 'Bob';
59, see the asynchronous programming codelab

Handling Streams

When you need to get values from a Stream, you have two options

  • Use
    Object name = 'Bob';
    61 and an asynchronous for loop (
    final name = 'Bob'; // Without a type annotation
    final String nickname = 'Bobby';
    29)
  • Use the Stream API, as described

Note. Before using

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
29, be sure that it makes the code clearer and that you really do want to wait for all of the stream’s results. For example, you usually should not use
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
29 for UI event listeners, because UI frameworks send endless streams of events

An asynchronous for loop has the following form

var name = 'Bob';
99

The value of

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
08 must have type Stream. Execution proceeds as follows

  1. Wait until the stream emits a value
  2. Execute the body of the for loop, with the variable set to that emitted value
  3. Repeat 1 and 2 until the stream is closed

To stop listening to the stream, you can use a

int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
44 or
int lineCount;

if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
75 statement, which breaks out of the for loop and unsubscribes from the stream

If you get a compile-time error when implementing an asynchronous for loop, make sure the

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
29 is in an
Object name = 'Bob';
61 function. For example, to use an asynchronous for loop in your app’s
Object name = 'Bob';
17 function, the body of
Object name = 'Bob';
17 must be marked as
Object name = 'Bob';
61

Object name = 'Bob';
00

For more information about asynchronous programming, in general, see the section of the library tour

Generators

When you need to lazily produce a sequence of values, consider using a generator function. Dart có hỗ trợ tích hợp cho hai loại hàm tạo

  • Máy phát điện đồng bộ. Returns an
    String name = 'Bob';
    26 object
  • Asynchronous generator. Returns a
    String name = 'Bob';
    25 object

To implement a synchronous generator function, mark the function body as

Object name = 'Bob';
63, and use
Object name = 'Bob';
60 statements to deliver values

Object name = 'Bob';
01

To implement an asynchronous generator function, mark the function body as

Object name = 'Bob';
62, and use
Object name = 'Bob';
60 statements to deliver values

Object name = 'Bob';
02

If your generator is recursive, you can improve its performance by using

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
46

Object name = 'Bob';
03

các lớp có thể gọi được

To allow an instance of your Dart class to be called like a function, implement the

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
47 method

Phương thức

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
47 cho phép bất kỳ lớp nào định nghĩa nó mô phỏng một hàm. Phương thức này hỗ trợ các chức năng giống như bình thường, chẳng hạn như tham số và kiểu trả về

Trong ví dụ sau, lớp

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
49 định nghĩa một hàm
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
47 nhận ba chuỗi và nối chúng lại, tách từng chuỗi bằng dấu cách và thêm một dấu chấm than. Nhấp vào Chạy để thực thi mã

Object name = 'Bob';
04

cô lập

Hầu hết các máy tính, ngay cả trên nền tảng di động, đều có CPU đa lõi. Để tận dụng tất cả các lõi đó, theo truyền thống, các nhà phát triển sử dụng các luồng bộ nhớ dùng chung chạy đồng thời. Tuy nhiên, đồng thời trạng thái chia sẻ dễ bị lỗi và có thể dẫn đến mã phức tạp

Thay vì các luồng, tất cả mã Dart chạy bên trong các phân lập. Mỗi cô lập Dart sử dụng một luồng thực thi duy nhất và không chia sẻ các đối tượng có thể thay đổi với các cô lập khác. Quay nhiều cô lập tạo ra nhiều luồng thực thi. This enables multi-threading without its primary drawback,

For more information, see the following

  • Concurrency in Dart
  • dart. isolate API reference, including Isolate. spawn() and TransferableTypedData
  • Background parsing cookbook on the Flutter site
  • Isolate sample app

Typedefs

A type alias—often called a typedef because it’s declared with the keyword

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
51—is a concise way to refer to a type. Here’s an example of declaring and using a type alias named
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
52

Object name = 'Bob';
05

A type alias can have type parameters

Object name = 'Bob';
06

Version note. Before 2. 13, typedefs were restricted to function types. Using the new typedefs requires a of at least 2. 13

We recommend using instead of typedefs for functions, in most situations. However, function typedefs can still be useful

Object name = 'Bob';
07

Metadata

Use metadata to give additional information about your code. Chú thích siêu dữ liệu bắt đầu bằng ký tự

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
53, theo sau là tham chiếu đến hằng số thời gian biên dịch (chẳng hạn như
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
54) hoặc gọi hàm tạo hằng số

Three annotations are available to all Dart code.

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
55,
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
56, and
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
91. For examples of using
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
91, see . Here’s an example of using the
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
55 annotation

Object name = 'Bob';
08

You can define your own metadata annotations. Here’s an example of defining a

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
60 annotation that takes two arguments

Object name = 'Bob';
09

And here’s an example of using that

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
60 annotation

Object name = 'Bob';
10

Metadata can appear before a library, class, typedef, 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

A single-line comment begins with

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
62. Mọi thứ giữa
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
62 và cuối dòng đều bị trình biên dịch Dart bỏ qua

Object name = 'Bob';
11

Nhận xét nhiều dòng

Chú thích nhiều dòng bắt đầu bằng

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
64 và kết thúc bằng
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
65. Mọi thứ giữa
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
64 và
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
65 đều bị trình biên dịch Dart bỏ qua (trừ khi nhận xét là nhận xét tài liệu; xem phần tiếp theo). Nhận xét nhiều dòng có thể lồng vào nhau

Object name = 'Bob';
12

Nhận xét tài liệu

Nhận xét tài liệu là nhận xét nhiều dòng hoặc một dòng bắt đầu bằng

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
68 hoặc
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
69. Sử dụng
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
68 trên các dòng liên tiếp có tác dụng tương tự như nhận xét tài liệu nhiều dòng

Bên trong một nhận xét tài liệu, bộ phân tích bỏ qua tất cả văn bản trừ khi nó được đặt trong ngoặc đơn. Sử dụng dấu ngoặc, bạn có thể tham chiếu đến các lớp, phương thức, trường, biến cấp cao nhất, hàm và tham số. Tên trong ngoặc được giải quyết trong phạm vi từ vựng của phần tử chương trình được ghi lại

Dưới đây là một ví dụ về nhận xét tài liệu có tham chiếu đến các lớp và đối số khác

Object name = 'Bob';
13

Trong tài liệu do lớp tạo ra,

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
71 trở thành liên kết đến tài liệu cho phương pháp
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
72 và
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
73 trở thành liên kết đến tài liệu cho lớp
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
74

Để phân tích mã Dart và tạo tài liệu HTML, bạn có thể sử dụng công cụ tạo tài liệu của Dart,

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
75. Để biết ví dụ về tài liệu được tạo, hãy xem tài liệu API Dart. Để được tư vấn về cách cấu trúc nhận xét của bạn, hãy xem Phi tiêu hiệu quả. Tài liệu

Summary

This page summarized the commonly used features in the Dart language. Nhiều tính năng đang được triển khai, nhưng chúng tôi hy vọng rằng chúng sẽ không phá vỡ mã hiện có. Để biết thêm thông tin, hãy xem Đặc tả ngôn ngữ phi tiêu và Phi tiêu hiệu quả

Hàm ẩn danh trong PHP là gì?

Hàm ẩn danh, còn được gọi là bao đóng, cho phép tạo các hàm không có tên cụ thể . Chúng hữu ích nhất với vai trò là giá trị của các tham số có thể gọi được, nhưng chúng cũng có nhiều cách sử dụng khác. Các hàm ẩn danh được triển khai bằng lớp Đóng.

Chức năng ẩn danh dùng để làm gì?

Hàm ẩn danh là một hàm không được lưu trữ trong tệp chương trình, nhưng được liên kết với một biến có kiểu dữ liệu là function_handle. Các hàm ẩn danh có thể chấp nhận nhiều đầu vào và trả về một đầu ra . Chúng chỉ có thể chứa một câu lệnh thực thi duy nhất.

Hai cách sử dụng phổ biến của các chức năng ẩn danh là gì?

Chúng ta có thể sử dụng hàm ẩn danh trong JavaScript cho một số mục đích. Một số trong số họ được đưa ra dưới đây. Truyền hàm ẩn danh cho hàm khác làm đối số . Chúng ta cũng có thể sử dụng một hàm ẩn danh làm đối số cho một hàm khác.

Tại sao lại sử dụng hàm ẩn danh trong go?

Hàm ẩn danh là một hàm không chứa bất kỳ tên nào. It is useful when you want to create an inline function . Trong ngôn ngữ Go, một hàm ẩn danh có thể tạo thành một bao đóng. Một chức năng ẩn danh còn được gọi là chức năng chữ.