Tips: This article only lists the important and strange syntax in Dart, so it is not suitable for those who have no foundation in other languages. Welcome to follow the official wechat account: FSA Full stack action 👋

Dart basic syntax

1. Program entry

  • Dart’s entry is also main and does not return a value.
  • Command line arguments passed to main are storedList<String> argsIn the.
  • Strings can be defined using either single or double quotation marks.
  • Each line statement must end with a semicolon.
main(List<String> args) {
  print("Hello World");
}
Copy the code

2. Declare variables

  • Variable type Variable name = assignment;
  • Var /dynamic/const/final = assignment;
// 1. Explicit statement
String name = "lqr";

Var /final/const
// There is no explicit way to specify the type of a variable, but the variable has its own explicit type
// 2.1 var Declares variables
var age = 18;
// age = "abc"; // IDE error: A value of type 'String' can't be assigned to A variable of type 'int'.

// 2.2 final Declares constants
final height = 1.88;
/ / height = 2.00; // The final variable 'height' can only be set once.

// 2.3 const Declares a constant
const address = "Guangzhou";
// address = "Beijing "; // IDE error: Constant variables can't be assigned a value.

// 2.4 Final and const
// Const must be assigned a constant value (a certain value is required at compile time)
// Final can obtain a value by evaluating the/function (a value is determined at run time)
// const date1 = DateTime.now(); // It's not the same
final date2 = DateTime.now();

// 2.5 Object and Dynamic differences
// Use Object and Dynamic, respectively, to make the parent class reference to the subclass Object
// Object calls a method, an error is reported at compile time
Object obj = "lqr";
print(obj.substring(1)); The method 'substring' isn't defined for The type 'Object'.
// dynamic calls the method without error at compile time, but there are security risks at run time
// Dynamic is an explicit declaration (var is a type derivation)
dynamic obj = "lqr";
print(obj.substring(1)); // qr
Copy the code

3. [Dart does not have] either zero or true

Non-zero true, non-null true features exist in JS, but not in Dart!! Dart requires that the if() statement must pass in a bool:

// There is no non-zero or non-null or true in Dart
var flag = "true";
if (flag) { Conditions must have a static type of 'bool'.
  print("Execute code");
}
Copy the code

Note: Dart does not support null-true or zero-true, and must have an explicit bool

4. String type

Dart defines strings in three ways:

  • Single quotation marks (“) : Same as double quotation marks.
  • Double quotation marks (“”) : the same as single quotation marks.
  • Triple quotation marks (“”””””) : You can define multi-line strings without any help\n.
// 1. Define a string
var str1 = 'abc';
var str2 = "abc";
var str3 = """
abc
cba
nba
""";

// Tip: If double quotes exist in a string and you don't want to escape them, you can define the string using single quotes and vice versa.
print('a"b"c'); // a"b"c
print("a'b'c"); // a'b'c
Copy the code

Dart supports string interpolation:

// 2. String and expression concatenation
var name = "lqr";
var age = 19;
var height = 1.88;
${variable} can be omitted from {}. ${expression} can be omitted from {}.
// var message1 = "my name is ${name}, age is ${age}, height is ${height}";
var message1 = "my name is $name, age is $age, height is $height"; // my name is lqr, age is 19, height is 1.88
var message2 = "name is $name, type is ${name.runtimeType}"; // name is lqr, type is String
print(message1);
print(message2);
Copy the code

5. Collection types

The Dart collection types are:

  • List: [ele1, ele2, ele2, ele1]
  • Set Set: {ele1, ele2, ele3}
  • Mapping Map: {“key1” : value1, “key2” : value2}
// 1. List: [];
var names = ["abc"."cba"."nba"."cba"];
names.add("mba");
// names.remove(value);
// names.removeAt(index);

// 2. 集合Set:{};
var movies = {"Interstellar"."A Chinese Odyssey".Inception};
names = Set<String>.from(names).toList(); // Set can be used to cancel
print(names);

// 3
var info = {
  "name": "lqr"."age": 18};Copy the code

Dart function use

1. Basic use of functions

Dart function definition:

The name of the function (argument list) {function body return return value}Copy the code

Example:

main(List<String> args) {
  print(sum(20.30));
}

int sum(int num1, int num2) {
  return num1 + num2;
}

// The type of the return value can be omitted (not recommended in development)
// sum(int num1, int num2) {
// return num1 + num2;
// }
Copy the code

2. Optional arguments to the function

Dart function parameters are of two types:

  • Mandatory: Mandatory
  • Optional parameter: No upload
main(List<String> args) {
  sayHello1("lqr");
}

// Mandatory: Mandatory
void sayHello1(String name) {
  print(name);
}
Copy the code
  • There are two optional parameters:
    • [int age, double height]
    • Name optional arguments: {int age, double height}
main(List<String> args) {
  sayHello2("lqr");
  sayHello2("lqr".18.1.88);

  sayHello3("lqr", age: 18, height: 1.88);
  sayHello3("lqr", height: 1.88, age: 18);
  sayHello3("lqr", height: 1.88);
}

// Position optional: [int age, double height]
// Arguments and parameters are matched by position
void sayHello2(String name, [int age, double height]) {}

// Name optional arguments: {int age, double height}
// Arguments and parameters are matched by variable names
void sayHello3(String name, {int age, double height}) {}
Copy the code

3. Default arguments to the function

No function overloading in Dart!! No function overloading in Dart!! No function overloading in Dart!! However, the Dart function supports setting default values for optional parameters:

void sayHello1(String name) {
  print(name);
}
Dart has no function overloading
Void sayHello1(){The name 'sayHello1' is already defined.
/ /...
// }

// Note: Only optional parameters can have default values. Mandatory parameters do not have default values
void sayHello4(String name, [int age = 20.double height = 1.7]) {}
void sayHello5(String name, {int age = 20.double height = 1.7{}})Copy the code

Note: Default values can be set only with optional parameters.

4. Functions are first-class citizens

A function being a first-class citizen means that it can be assigned to a variable or used as an argument or return value of another function.

main(List<String> args) {
  // 1. Find another defined function and pass it in
  test(bar); // the bar function is called

  // 2. Anonymous function (argument list){function body};
  test(() {
    print("Anonymous function called"); // An anonymous function is called
    return 10;
  });

  // 3. Arrow function: conditional, function body has only one line of code
  // Note: Dart arrow functions are different from js arrow functions
  test(() => print("Arrow function called")); // The arrow function is called
}

// A function can be an argument to another function
void test(Function foo) {
  var result = foo();
}

void bar() {
  print("Bar function called");
}
Copy the code

The problem with using Function as an argument to another Function is that there is no way to restrict the Function passed in:

main(List<String> args) {
  test((name) {
    print(name); // lqr
  });
}

// Encapsulate the test function, which requires passing in a function
// Disadvantages: Function cannot restrict the Function passed in (e.g. Function argument list, return value)
void test(Function foo) {
  foo("lqr");
}
Copy the code

In this case, you can use Function signatures instead of Function:

main(List<String> args) {
  test((num1, num2) {
    return num1 + num2;
  });
}

// You can restrict the types of functions that take arguments
// Disadvantages: it is equivalent to writing a function declaration (function signature) on the parameter position
void test(int foo(int num1, int num2)) {
  foo(20.30);
}
Copy the code

For better readability, use a typedef instead of a function signature:

main(List<String> args) {
  test((num1, num2) {
    return num1 + num2;
  });

  var demo1 = demo();
  print(demo1(20.30)); / / 600
}

// Use a typedef to define a function type
typedef Calculate = int Function(int num1, int num2);

void test(Calculate calc) {
  calc(20.30);
}

// function as return value
Calculate demo() {
  return (num1, num2) {
    return num1 * num2;
  };
}
Copy the code

Dart special operators

1. Operators

  • ?? =: assignment operator (perform assignment only if the variable is null)
  • ??: conditional operator (sort of like a simplified ternary operator)
/ / 1.?? =
// When the original variable has a value, then?? = does not perform
// If the original variable is null, the value is assigned to the variable
var name = null; name ?? ="lilei";
print(name); // lilei

// 2. ??
/ /?? If the previous data has a value, use?? Previous data
/ /?? If the previous data is NULL, the later value is used
var name = null;
var temp = name ?? "lilei";
print(temp); // lilei
Copy the code

2. Cascading method (..)

Dart can be cascaded (..) Change any object’s variable assignment or method call to a chained call:

main(List<String> args) {
  // var p = Person();
  // p.name = "lqr";
  // p.run();
  // p.eat();

  // cascade operator
  varp = Person() .. name ="lqr". eat() .. run(); }Copy the code

3. Use of the for loop

Dart supports normal for loops, as well as for-In loops:

// 1. Base for loop
for (var i = 0; i < 10; i++) {
  print(i);
}

// 2
var names = ["why"."cba"."cba"];
for (var i = 0; i < names.length; i++) {
  print(names[i]);
}

for (var name in names) {
  print(name);
}
Copy the code

While and do-while are consistent with other languages, as are the use of break and continue

Dart object orientation

1. Class definition

Dart uses the class keyword to define classes:

main(List<String> args) {
  var p1 = new Person("lqr".18);
  // Starting with Dart2, the new keyword can be omitted
  var p2 = Person("lqr".18);
}

class Person {
  String name;
  int age;

  // Person(String name, int age) {
  // this.name = name;
  // this.age = age;
  // }

  // Equivalent to the code above
  Person(this.name, this.age);
}
Copy the code

Class constructor

Dart does not support function overloading, so constructors cannot be overloaded either. However, you can use the named constructor to solve the problem:

main(List<String> args) {
  var p = Person("lqr".18);
  var p1 = new Person.withNameAgeHeight("lqr".18.1.88);
  var p2 = Person.fromMap({
    "name": "lqr"."age": 18."height": 1.88}); }class Person {
  String name;
  int age;
  double height;

  Person(this.name, this.age);

  There are no function overloads in Dart
  // Person(this.name, this.age, this.height); // IDE error: The default constructor is already defined

  // Name the constructor
  Person.withNameAgeHeight(this.name, this.age, this.height);

  Person.fromMap(Map<String.dynamic> map) {
    this.name = map['name'];
    this.age = map['age'];
    this.height = map['height'];
  }

  @override
  String toString() {
    return "$name $age $height"; }}Copy the code

Class initialization list

If a property ina class uses a final modifier, the final property must be assigned in the constructor, but it is important to note that the final property cannot be assigned in the constructor’s body:

class Person {
  final String name;
  final int age;

  // Person(this.name, this.age) {} // Mandatory parameters
  Person(this.name, {this.age = 10{}})// (with default values) This parameter is optional

  // Person(this.name) {// All final variables must be initialized, but 'age' isn't.
  // this.age = 10; // IDE error: 'age' can't be used as a setter because it's final.
  // }
}
Copy the code

While Dart does not support assigning final attributes in the constructor body, it is possible to assign them using initializer lists:

Initializers are used in conjunction with named optional parameters to validate the parameters’ properties and set their initial values when the constructor is called.

class Person {
  final String name;
  final int age;

  // function (): XXXXXX {
  Person(this.name) : this.age = 10 {} // Initializer list: It is possible to assign values to attributes using expressions
  // Person(this.name, {this.age = 10}) {} // (with default) Optional arguments: Only assignment statements can be used to assign attributes
  Person(this.name, {int age}) : this.age = age?? 10 {

  // If there are multiple initializers, separate them with commas
  // Person(this.name, {int age, double height}) : this.age = age?? 10, this.height = height?? 1.88 {}
}
Copy the code

Redirect constructor

To redirect the constructor, call another constructor within a constructor:

class Person {
  String name;
  int age;

  // Constructor redirection
  Person(String name) : this._internal(name, 0);

  Person._internal(this.name, this.age);
}
Copy the code

Constant constructors

In some cases, we want to pass in the same value to return the same object. In this case, we can use the constant constructor:

  • Constant constructors:
    • Before the constructorconstModify.
    • In a class that has a constant constructor, all member variables must be usedfinalModification.
    • Instead of using the new keyword to create the same object through the constant constructor, useconstThe keyword.
      • If I assign the result toconstTo modify the identifier,constYou can omit it.
main(List<String> args) {
  // To receive the result of a constant constructor, omit const
  // const p1 = const Person("lqr", 18);
  const p1 = Person("lqr".18);
  const p2 = Person("lqr".18);
  print(identical(p1, p2)); // true

  // If we use var to receive the result of a constant constructor, instead of const, we omit new!!
  var p11 = Person("lqr".18); // ==> var p11 = new Person("lqr");
  var p22 = Person("lqr".18);
  print(identical(p11, p22)); // false

  // All attributes must have the same value
  const p111 = Person("lqr".18);
  const p222 = Person("lqr".20);
  print(identical(p111, p222)); // false
}

class Person {
  // In a class with a constant constructor, all member variables must be final
  final String name;
  final int age;

  // There can be only one constant constructor in a class, not even a named constructor
  // const Person(this.name);
  const Person(this.name, this.age);
}
Copy the code

Factory constructors

To satisfy the need to pass in the same value and get the same object, you can use the factory constructor in addition to the constant constructor, and the factory constructor is more flexible.

  • Factory constructor: Prefixes the constructorfactoryThe keyword is modified.
  • Factory constructors differ from normal constructors:
    • Normal constructor: returns the created object automatically, not manually
    • The best feature of the factory constructor is that it can manually return an object
main(List<String> args) {
  final p1 = Person.withName("lqr");
  final p2 = Person.withName("lqr");
  print(identical(p1, p2));
}

class Person {
  String name;
  String color;

  // Static attributes are class attributes and can be called directly from the class name
  static final Map<String, Person> _nameCache = {};

  Person(this.name, this.color);

  // A normal constructor returns the created object automatically, not manually
  // The factory constructor can return an object manually
  factory Person.withName(String name) {
    if (_nameCache.containsKey(name)) {
      return _nameCache[name];
    } else {
      final p = Person(name, "default");
      _nameCache[name] = p;
      returnp; }}}Copy the code

Setters and getters for classes

Most of the time, we don’t want object fields to be directly accessed by the outside world, but rather via setters and getters. The advantage of this is that you can do some extra work in setters and getters. Dart supports adding setters and getters to fields:

  • setter: Used beforesetDeclare, and need to use(a)Receive parameters.
  • getter: Used beforegetDeclare, you also need to declare the return value type, but you can’t have one(a)Receive parameters.
  • settergetterUse it like a field.
main(List<String> args) {
  final p1 = Person();

  // p1.setName("lqr"); The method 'setName' isn't defined for The type 'Person'.

  // Setters and getters are used like fields
  p1.setName = "lqr";
  print(p1.getName); // lqr
}

class Person {
  String name;

  // setter
  // set setName(String name) {
  // this.name = name;
  // }
  set setName(String name) => this.name = name;

  // getter: notice that the getter has no ()
  // String get getName {
  // return this.name;
  // }
  String get getName => this.name;
}
Copy the code

Setters and getters in Dart are no longer strictly methods.

Class inheritance

Inheritance in Dart uses the extends keyword, and subclasses use super to access the parent class.

Note: Dart supports only single inheritance.

main(List<String> args) {}

class Animal {
  int age;

  Animal(this.age);

  void run() {
    print("Run forward."); }}class Person extends Animal {
  String name;

  // The constructor of the parent class must be called in the initializer
  Person(this.name, int age) : super(age);

  @override
  void run() {
    // super.run();
    print("Move on."); }}// Dart supports only single inheritance
// Class SuperMan extends Runner, Flyer{// IDE extends clause: Each class definition can hava at most one
// }
Copy the code

Use of abstract classes

Dart can define abstract classes using the abstract keyword:

  • In an abstract classAbstract methods do not need to use the abstract keyword modifier
  • Abstract classes cannot be instantiated
main(List<String> args) {
  final s = Shape(); // IDE error: Abstract classes can't be instantiated.
}

// Note 2: Abstract classes cannot be instantiated
abstract class Shape {
  // An abstract method, without a method body and without the abstract keyword modifier
  int getArea();

  String getInfo() {
    return "Shape"; }}// Note 1: After inheriting from an abstract class, you must implement the abstract methods of the abstract class
class Rectangle extends Shape {
  @override
  int getArea() {
    return 100; }}Copy the code

Note: Abstract classes cannot be instantiated in Dart, but there are special cases where an abstract class with a factory constructor can be instantiated, such as Map.

10. Implicit interfaces

Dart implements multiple interfaces using the implements keyword, but Dart doesn’t have an interface definition keyword. By default, all classes are implicit, which means they can be implemented by any class:

Note: Rewrite all methods in the class that implements!

main(List<String> args) {}

// Dart does not have a keyword to define an interface
// There are no such keywords interface/protocol
// All classes are implicit interfaces by default
class Runner {
  void running() {
    print("Run!"); }}class Flyer {
  void flying() {
    print("Fly"); }}// When using a class as an interface, the class implementing the interface must implement all methods in the interface (do not use super in those methods)
class SuperMan implements Runner.Flyer {
  @override
  void flying() {
    // super.flying(); // IDE error: The method 'flying' is always in The supertype.
  }

  @override
  void running() {}
}
Copy the code

Suggestion: Use abstract class to declare interfaces; all methods of classes that are implemented need to be overridden anyway.

11. The use of mixin

What do you do when you need to reuse methods in two classes?

  • If you use the interface approach, you need to re-implement the methods in both classes, which is not reuse at all.
  • Dart can only be single-inherited, and can only reuse methods in one class at most.

Dart offers another solution: Mixin. You can define two mixin classes and use the with keyword to mix the two mixin classes into A class A. Then class A owns their methods, so as to achieve the purpose of reusing the methods in the two classes:

main(List<String> args) {
  final superMan = SuperMan();
  superMan.eating(); // Take action to eat
  superMan.running(); // running(call running() mixed with class Runner)
  superMan.flying(); // flying
}

class Animal {
  void eating() {
    print("Action eating.");
  }

  void running() {
    print("Animal running"); }}mixin Runner {
  void running() {
    print("running"); }}mixin Flyer {
  void flying() {
    print("flying"); }}// Running () in Runner conflicts with running() in Animal, and overwriting occurs, i.e. running() in Runner calls running() in SuperMan.
class SuperMan extends Animal with Runner.Flyer {}
Copy the code

Class properties and class methods

Class properties and methods can be called directly from the class name: static class properties (or methods); static class properties (or methods);

main(List<String> args) {
  Person.courseTime = "8";
  print(Person.courseTime);
  Person.gotoCourse();
}

class Person {
  // Member variables
  String name;

  // Static attributes (class attributes)
  static String courseTime;

  // Object method
  void eating() {
    print("eating");
  }

  // Static method (class method)
  static void gotoCourse() {
    print("Go to class"); }}Copy the code

13. Use of enumerations

Enumerations are defined using the enum keyword and have two common attributes:

  • Index: The index used to represent each enumeration, starting at 0
  • Values: A collection containing each enumerated value
// enumeration: enum
main(List<String> args) {
  final color = Colors.red;
  switch (color) {
    case Colors.red:
      print("Red");
      break;
    case Colors.blue:
      print("Blue");
      break;
    case Colors.green:
      print("Green");
      break;
  }

  print(Colors.values); // [Colors.red, Colors.blue, Colors.green]
  print(Colors.red.index); / / 0
}

enum Colors {
  red,
  blue,
  green,
}
Copy the code

Use of generics

Collection types use generics:

// List is used as a generic form:
var names1 = ["abc"."cba"."nba".111]; // List<Object>
var names2 = ["abc"."cba"."nba"]; // List<String>
// var names3 = 
      
       ["abc", "cba", "nba", 111]; The element type 'int' can't be assigned to The list type 'String'.
      
var names3 = <String> ["abc"."cba"."nba"]; // List<String>
List<String> names4 = ["abc"."cba"."nba"]; // List<String>

// Map is used with generic notation:
var info1 = {"name": "lqr"."age": 18}; // _InternalLinkedHashMap<String, Object>
var info2 = <String.String> {'name': 'lqr'.'age': '18'}; // _InternalLinkedHashMap<String, String>
Map<String.String> info3 = {'name': 'lqr'.'age': '18'}; // _InternalLinkedHashMap<String, String>
Copy the code

Class definitions use generics:

main(List<String> args) {
  var point = Point<double> (1.23333.1.9527); // Point<double>
  final pointX = point.setAndGetX(5.55);
  print(pointX); / / 5.55
}

// Class Point
      
        //
      
class Point<T extends num> { // The generic T is a numeric type
  T x;
  T y;

  Point(this.x, this.y);

  T setAndGetX(T x) {
    this.x = x;
    return this.x; }}Copy the code

T extends num specifies that the type of a generic must be a number. Otherwise, the default is Object.

Use of libraries in Dart

  • Dart allows you to import a library to use the functionality it provides.
  • Any Dart file in Dart is a library, even if you don’t use keywordslibraryThe statement.

Library import syntax:

import 'Uri of library';
Copy the code

1. Use the system’s library

System library URIs generally start with DART:. Common system libraries include DART: IO, DART :async, dart:math, and so on.

// import 'dart:io';
// import 'dart:isolate';
// import 'dart:async';
// import 'dart:math';

// System library: import 'dart: library name ';

import 'dart:math';

main(List<String> args) {
  final num1 = 20;
  final num2 = 30;
  print(min(num1, num2));
}
Copy the code

Note: Dart: Core is also a common system library, but can be omitted.

2. Use custom libraries

A custom library is another DART file defined in your project, such as a math_utils.dart file in the utils directory that looks like this:

Dart = math_utils; dart = math_utils;
int sum(int num1, int num2) {
  return num1 + num2;
}

int mul(int num1, int num2) {
  return num1 * num2;
}
Copy the code

The math_utils.dart file here is a custom library that you can import in other DART files:

// Import custom libraries can be relative or absolute paths.
import 'utils/math_utils.dart';

main(List<String> args) {
  print(sum(20.30));
Copy the code

3. Use third-party libraries

Yaml < span style = “box-sizing: box-sizing: inherit! Important; word-spacing: inherit! Important;”

name: myProjectName
description: my project name
dependencies:
  http: ^ 0.12.0 + 4
environment:
  sdk: "> = 2.10.0 < 3.0.0"
Copy the code

You can find instructions for third-party libraries at pub.dev.

After the dependencies have been filled in, dart pub get or flutter pub get commands should be executed to enable the terminal to pull the corresponding version file of the third party from the server, and then the third party library can be used in the code:

import 'package:http/http.dart' as http;

main(List<String> args) async {
  var url = 'https://example.com/whatsit/create';
  var response = await http.post(url, body: {'name': 'doodle'.'color': 'blue'});
  print('Response status: ${response.statusCode}');
  print('Response body: ${response.body}');
  print(await http.read('https://example.com/foobar.txt'));
}
Copy the code

4. Library method name conflicts

Dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart = math_utils.dart

import 'utils/math_utils.dart';

main(List<String> args) {
  print(sum(20.30)); This experssion has a type of 'void' so its value can't be used.
}

// void sum(num1, num2) // The parameter type is dynamic
void sum(int num1, int num2) {
  print(num1 + num2);
}
Copy the code

Dart file recognizes its own sum() method when in fact we want to use the sum() method in math_utils.dart. This creates a library method name conflict, which can be resolved by using the as keyword to alias the library:

import 'utils/math_utils.dart' as mUtils;

main(List<String> args) {
  print(mUtils.sum(20.30));
}

void sum(sum1, sum2) {
  print(sum1 + sum2);
}
Copy the code

5. Display and hide library contents

By default, all content in the imported library is visible, but many times we want to import only some content in the library, or we want to hide some content in the library, using the show and hide keywords:

  • Show: show one member (block others)
// import "utils/math_utils.dart" show sum, mul;
import "utils/math_utils.dart" show sum;

main(List<String> args) {
  print(sum(20.30));
  print(mul(20.30)); // The function 'mul' isn't defined.
}
Copy the code
  • Hide: Hides a member (shows others)
// import "utils/math_utils.dart" hide sum, mul;
import "utils/math_utils.dart" hide sum;

main(List<String> args) {
  print(sum(20.30)); // The function 'sum' isn't defined.
  print(mul(20.30));
}
Copy the code

6. Import library files in batches

In some cases, you may need to import n libraries in a DART file, which is acceptable:

import 'utils/math_utils.dart';
import 'utils/date_utils.dart';
import. main(List<String> args) {
  print(sum(20.30));
  print(dateFormat());
}
Copy the code

But what if n DART files are imported into the same M libraries? Clearly, there is a need for a unified batch import of library files: you can create a new DART file and use the export keyword to unify the library.

// utils. Dart file contents in utils directory:
export 'math_utils.dart';
export 'date_utils.dart';
export.Copy the code

In other DART files, just import this utils.dart:

import 'utils/utils.dart';

main(List<String> args) {
  print(sum(20.30));
  print(dateFormat());

  _min() in math_utils.dart cannot be called from outside
  // print(_min(20, 30)); // The function '_min' isn't defined.
}
Copy the code

Note: There are no visibility modifiers in the Dart language, i.e. public, protected, and private. If a member attribute or method does not want to be called by outsiders (other DART files), you can prefix the name with an underscore _.

Dart Extension provides the following functions

Dart has added the Extension syntax since version 2.7, which allows you to extend member methods to existing classes. The extension class method needs to use the extension keyword. The syntax is:

extension XXX on YYY{}
Copy the code

The extension name is XXX (the name can be written freely).

1. Extend member methods

If you want to extend a member method to String, you can write:

extension StringExt on String {
  String sayHello() {
    return "hello $this";
  }
}

main(List<String> args) {
  final name = "GitLqr";
  print(name.sayHello()); // hello GitLqr
}
Copy the code

2. Extend operators

Extension can also extend operators, such as:

extension StringExt on String {
  operator* (int count) {
    String result = "";
    for (var i = 0; i < count; i++) {
      result += this;
    }
    return result;
  }
}

main(List<String> args) {
  final name = "GitLqr";
  print(name * 3); // GitLqrGitLqrGitLqr
}
Copy the code

3, extend member “attributes”

Extension can extend getters and setters as well as methods and operators, but cannot extend instance attributes (or fields). However, because getters are called with the same syntax as properties, “properties” are quoted:

extension StringExt on String {
  int get size {
    return this.length;
  }
}

main(List<String> args) {
  final name = "GitLqr";
  print(name.size); / / 6
}
Copy the code

Dart. Dev /guides/lang…

If this article is helpful to you, please click on my wechat official number: FSA Full Stack Action, which will be the biggest incentive for me. The public account not only has Android technology, but also iOS, Python and other articles, which may have some skills you want to know about oh ~