The subject catalog of Flutter: this catalog helps you quickly find out what you want to learn!!

This post continues with the Flutter- From Introduction to Project 04:Dart Grammar Quick Mastery (part 1) Analysis. As you can see from the previous post, people don’t like reading grammar related articles. But no matter I still continue to write: after all, if you want to do a good job, you must first sharpen its tools

All landowners function

Dart is an object-oriented language, so even though functions are objects, there is 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 the Dart class as if it were a function. For more information, see: Callable -classes

// Function type tests
// Void represents the return value type
FuncFunc represents the name of the function
/ / () parameters
void funcFunc(){
}

// Omitted: no type is declared
funcFunc1(){
}
// For methods that contain only one expression, you can use a shorthand syntax:
funcFunc2() => print("=> "; Syntax is short for {return expression}");
Copy the code

Note: only one expression can be used at the arrow (=>) and semicolon (;). Statements cannot be used in this way. For example, you can’t put an if statement between these two symbols, but a ternary operator (? πŸ™‚ yes.

  • A function can have two types of arguments: required and optional. All necessary parameters should be listed before the optional parameters. Optional parameters can be added after the required parameters have been listed.

  • An optional parameter can be an optional positional parameter or an optional named parameter, but cannot be both.

  • Default values can be defined for either of these optional parameters. But the default value must be a compile-time constant, such as a literal. If no default value is provided for this parameter, the default value for this parameter will be null.

/// Use bold and hidden as the values of your declared parameters
funcFunc3({bool bold, bool hidden}) {
  print('$bold.$hidden');  // true,null
}
/ / call
funcFunc3(bold: true);

/// Use bold and hidden as your declared parameters, and the default values are false and True, respectively
funcFunc4({bool bold = false.bool hidden = true{})print('$bold.$hidden');   // false,true
}
// The default values are optional
funcFunc4();


// Optional positional arguments, marked as optional positional arguments with [] :
String funcFunc5(String person , String word, [String device]) {
  var result = "$person say : $word"; 
  if(device ! =null){
    result = "$person say : $device"; 
  }
  print(result);
  return result;
}
// Call the function
funcFunc5("KC"."Study in harmony, without haste or impatience.");  KC say: Study in harmony, not in haste or impatience
funcFunc5("KC"."Study in harmony, without haste or impatience."."It's better to chase the wind than wait for it."); KC say: It's better to chase after the wind than wait for it
Copy the code
  • Function as a class object -> pass a function as an argument to another function.Functional programming ideas
// Functional programming ideas
funcFunc6(int num) = >print(num);

funcFunc7(){
  var list = [1.2.3.4];
  list.forEach(funcFunc6);
  /**
      flutter: 1
      flutter: 2
      flutter: 3
      flutter: 4
   * /
}
Copy the code
  • Anonymous functions

Most functions can be named anonymously, such as main() or printElement(). You can also create an anonymous function called an anonymous function, and sometimes a lambda or a closure. You can assign an anonymous function to a variable, for example, you can add or remove it from a collection.

An anonymous function looks like a named function with arguments of -0 or more, separated by commas and optional type annotations between parentheses.

The following code block contains the body of the function:

 ([[Type] param1 [,...]. ]) { codeBlock; };Copy the code

The following example defines an anonymous function item with untyped arguments that is called by each item ‘in the list and outputs a string containing the value at the specified index.

var list = ['apples'.'bananas'.'oranges'];
 list.forEach((item) {
    print('${list.indexOf(item)}: $item');
 });
Copy the code

Today operator

introduce symbol
Unary suffix expr++ expr– () [] .
Unary prefix -expr ! expr ~expr ++expr –expr
Multiplication type * / % ~ /
Addition type + –
An operator << >>
Bitwise and &
The bitwise exclusive or ^
Bitwise or |
Compare and type test >= <= > < as is is!
equivalent = =! =
Logic and &&
Logic or ||
Conditional operator expr1 ? expr2 : expr3
Cascade operator .
The assignment = * = / = = ~ / = % = + = – = < < = > > = & = ^ = | =

Whether theseThe operatororArithmetic operator,Equivalence and relational operators,Type test operator 、Assignment operator 、Logical operator 、 Bit operations and shift operatorsJust like any other language! So just take a peek

Cascade:.Allows you to perform multiple operations on members of a single object, specifically visibleclass

⑨ Control flow statement

  • The if and the else
  • The for loop
  • While and do-while loops
  • Break and continue
  • The switch and the case
  • assert

You can also change the flow of control by using try-catch and throw, see the exceptions section for details.

The grammar here is pretty much the same as we do for iOS development, so if you want to be more proficient, you can learn The Flutter

πŸ”Ÿ Exception Statement

void excFunc(){
  try {
    print("KCFlutter");
  } on Exception catch (e) {
    // Any exception
    print('Comes the exception:$e');
  } catch (e) {
    // Non-specific type
    print('Non-specific types:$e'); }}Copy the code

Throw + catch + finally

11 the generic

If you look in the API documentation for the basic array type or List type, you’ll see that the type is actually List

, where <… The > tag indicates that the table is a generic type (or parameterized structure) — a type that contains parameters of a normal type. By convention, type variables are usually single-character names, such as E,T,S,K, and V.

  • For example, if you’re going to use a string onlyListYou can declare it asList<String>In this way, your fellow programmers, as well as your tools (such as the Dart editor and the Dart VIRTUAL machine in debug mode), can detect the assignment of a non-string variable toListIs probably wrong, here’s an example:
/ / generics
void genericsFunc(){
  var names = List<String> (); names.addAll(['Hank'.'Cooci'.'CC']);
  // names.add(100); // An error will be reported, because the generics determine the type of the contents of the list
}
Copy the code
  • Another reason to use generics isTo reduce code duplication.Generics allow you to share an interface and implementation for multiple typesIt still has advantages in debug mode and error warning for static analysis. For example, when you create an interface to cache an object:
// Generics allow you to share an interface and implementation for multiple types,
// It still has advantages in debug mode and error warning for static analysis
abstract class KCObjectCache{
  Object getByKey(String key);
  setByKey(String key,Object value);
}
// You find that you want a string specific interface, so you create another one:
abstract class KCStringCache{
  String getByKey(String key);
  setByKey(String key,String value);
}
// Next, you decide that you want a digital-only interface for this interface... You came up with this idea.
// Generic types make it easier for you to create these interfaces. Instead, you simply create an interface with a type parameter:
// Generics are the next big thing
abstract class Cache<T>{
  // In this code, T is an alternate type, a placeholder, which you can treat as a subsequent type defined by the developer.
  T getByKey(String key);
  setByKey(String key,T value);
}
Copy the code

12 class

This content is also the most important! At ordinary times everyone development is also a must, I hope you have a good experience ~~☺️

12.1 object

  • DartIs an object oriented language and supports a language based onmixinInheritance method.
  • DartAll objects in the language are instances of a class, and all classes have the same base classObject.
  • Based on themixinA class can inherit from multiple parent classes.
// Class related tests
class LGPerson {
  int age;
  String name;
  String hobby;
  double height;
}

void classFunc(){
  // The instance variable creates the test
  var person = LGPerson();
  person.age = 18;
  person.name = "Cooci";
  person.height = 182.0;
  person.hobby  = "iOS";

  print(person.runtimeType); // LGPerson
}
Copy the code
  • Use.(dot) to call an instance variable or method.

  • Use? To ensure that the previous operand is not null, often used instead of., to avoid throwing an exception if the left operand is null.

  • Get the type of the object at run using the runtimeType method. This method will return Type ‘

12.2 Instance Variables

  • In the class definition, all uninitialized variables are initialized to null.

  • Dart implicitly defines setter methods for all variables in the class definition, and adds getters for non-empty variables.

  var person2 = LGPerson();
  person2.hobby = "Flutter";  // Use the setter method for hobby.
  print(person2.hobby);       // Use the getter method for hobby.
  print("age = ${person2.age}, name = ${person2.name}"); //age = null, name = null
Copy the code

12.3 Constructors

To declare a constructor, simply create a method with the same name as the class (or add an extra identifier to name the constructor’s description). The most common form of a constructor is an automatically generated constructor that creates a new instance of a class:

class LGStudent {
  int age;
  String name;
  String hobby;
  double height;

  // LGStudent(int age, String name, String hobby){
  // // height has no constructed assignment
  // this.age = age;
  // this.name = name;
  // this.hobby = hobby;
  // }
  // The this keyword points to the instance of the current class. The above code can be simplified as:
  LGStudent(this.age,this.name,this.hobby);
}

  // The constructor
  var student1 = LGStudent(18."KC"."Constructor");
  print("age = ${student1.age}, name = ${student1.name}"); // age = 18, name = KC
Copy the code
  • If you do not declare a constructor, the system provides a default constructor. The default constructor takes no arguments and calls the parent class’s parameterless constructor. : LGStudent ()

  • A child class does not inherit the constructor of its parent class. Subclasses have only the default constructor. (No arguments, no named constructor).

  • Using named constructors allows you to declare multiple constructors for a class, or to provide additional declarations:

  // Name the constructor
  LGStudent.fromMap(Map stuMap){
    age    = stuMap['age'];
    name   = stuMap['name'];
    hobby  = stuMap['hobby'];
    height = stuMap['height'];
  }

  // Initialize the list
  LGStudent.fromMaplist(Map stuMap):
        age = stuMap['age'],
        name = stuMap['name'],
        hobby = stuMap['hobby'],
        height = stuMap['height'] {// age = 18, name = cool C, hobby = 1, height = 180.0
    print("age = $age, name = $name, hobby = $hobby, height = $height");
  }

  var stuMap   = {'age': 18.'name': 'cool C'.'hobby': "Master Bottom".'height': 180.0};var student2 = LGStudent.fromMap(stuMap);
  print("age = ${student2.age}, name = ${student2.name}"); // Age = 18, name = cool C
Copy the code

Redirect the constructor

Sometimes the purpose of a constructor is simply to redirect to another constructor in the same class. If the body of a redirected constructor is empty, then the constructor is called directly after the colon.

  // The this keyword points to the instance of the current class. The above code can be simplified as:
  LGStudent(this.age,this.name,this.hobby);
  // Redirect the constructor
  LGStudent.rediconstructor(int age, String name, String hobby) : this(age,
      Crying "C", hobby);  // : this is followed by a call to the above constructor
  var student4 = LGStudent.rediconstructor(20."KC".'185.');
  print("age = ${student4.age}, name = ${student4.name}, hobby = ${student4 .hobby}"); // age = 20, name = cry C, hobby = 185.
Copy the code

Static constructor

If your class produces objects that never change, you can make those objects compile-time constants. To do this, you need to define a const constructor and ensure that all instance variables are final.

// Static constructor
class LGTeacher{
  final num age;
  final String name;
  const LGTeacher(this.age, this.name);
  static final LGTeacher teacher = LGTeacher(300."No rush, no rush.");
}

  // Static constructor
  var teacher1 = LGTeacher(100."Harmonious Learning");
  // teacher1.age = 200; // Error: The setter 'age' isn't defined for The class 'LGTeacher' cannot be modified
  teacher1 = LGTeacher(200."Harmonious Learning");
  print("age = ${teacher1.age}, name = ${teacher1.name}"); // Age = 200, name = 1

  var teacher2 = LGTeacher.teacher;
  Teacher2 = LGTeacher(200, "teacher2 "); // Age = 200, name = 1
  print("age = ${teacher2.age}, name = ${teacher2.name}"); // Age = 300, name = no hurry
Copy the code

Factory constructor

When you implement a constructor decorated with the Factory keyword, the constructor does not have to create a new instance of the class. For example, the factory constructor might return instances from the cache, or it might return instances of subtypes. The following example demonstrates an object returned from the cache by a factory constructor:

// The factory constructor
class LGCar{
  String name;
  // The normal constructor
  LGCar.func(this.name);

  static final Map<String, LGCar> _cache = <String, LGCar>{};

  factory LGCar(String name){
    if (_cache.containsKey(name)){
      return _cache[name];
    }else{
      final car = LGCar.func(name);
      _cache[name] = car;
      returncar; }}}// The factory constructor
  var car = new LGCar("Ferrari");
  print("name = ${car.name}"); // Name = Ferrari
Copy the code

12.4 methods

Instance methods: Instance methods of an object can access instance variables and this

Setters and Getters

Is a special method that provides reading and writing to method attributes. Each instance variable has an implicit getter method and maybe a setter if appropriate. You can create additional properties by implementing getters and setters, using the get and set keywords directly:

class LGRectangle {
  num left;
  num top;
  num width;
  num height;

  LGRectangle(this.left, this.top, this.width, this.height);

  // Define two computed properties: right and bottom.
  num get right             => left + width;
  set right(num value)      => left = value - width;
  num get bottom            => top + height;
  set bottom(num value)     => top = value - height;
}

// Test the method
void methodFunc(){
  var rectangle = LGRectangle(10.20.100.300);
  print('right = ${rectangle.right}, bottom = ${rectangle.bottom}');// right = 110, bottom = 320

}
Copy the code

Abstract methods

The Instance, getter, and setter methods can be abstract, that is, defining an interface but leaving the implementation to another class. To create an abstract method, use the semicolon (;) Substitute method body:

// Abstract method
abstract class LGDoer {
  / /... Define instance variables and methods...
  void doSomething(); // Define an abstract method.
}

class LGEffectiveDoer extends LGDoer {
  void doSomething() {
    / /... Provides an implementation, so the methods here are not abstract...
    print("hello word"); }}Copy the code

12.5 Overloaded Operators

You can override the operators listed in the following table. For example, if you define a vector class, you can define a + method to add two vectors.

+ | []
> / ^ [] =
~ / & ~
> = * = =
% >>

Here’s an example of a class that overrides the + and – operators:

// Overloaded operators
class Vector {
  final int x;
  final int y;
  const Vector(this.x, this.y);

  /// Overrides + (a + b).
  Vector operator +(Vector v) {
    return new Vector(x + v.x, y + v.y);
  }

  /// Overrides - (a - b).
  Vector operator -(Vector v) {
    return newVector(x - v.x, y - v.y); }}void vectorFunc() {
  final v = new Vector(2.3);
  final w = new Vector(2.2);
  // v == (2, 3)
  assert(v.x == 2 && v.y == 3);
  // v + w == (4, 5)
  assert((v + w).x == 4 && (v + w).y == 5);
  // v - w == (0, 1)
  assert((v - w).x == 0 && (v - w).y == 1);
}
Copy the code

If you override ==, you should also override the getter method for hashCode in the object. For the rewriting == and hashCode examples, see Implementing Map Keys.

For more information about overloading, see Extending a class.

12.6 Implicit Interface

Each class implicitly defines an interface that contains all instances of the class and all interfaces it implements. If you want to create A class A that supports the API of class B, but does not want to inherit from class B, then class A should implement the interface of class B.

A class implements one or more interfaces by declaring them with the Implements clause and then providing API interface requirements. Such as:

// Implicit interface
// A KCPerson containing the implicit interface for greet().
class KCPerson {
  // In this interface, only the library is visible.
  final _name;
  // Not in the interface, because this is a constructor.
  KCPerson(this._name);
  // In this interface.
  String greet(who) => 'Hello, $who. I am $_name. ';
}

An implementation of the KCPerson interface.
class KCImposter implements KCPerson {
  // We have to define it, but we don't use it.
  final _name = "";
  String greet(who) => 'Hi $who. Do you know who I am? ';
}

greetBob(KCPerson person) => person.greet('bob');

imposterFunc() {
  print(greetBob(new KCPerson('KC')));
  print(greetBob(new KCImposter()));
}
Copy the code

Extending a class

Use extends to create a subclass, and supper will point to the superclass:

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ...
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ...
}
Copy the code

Subclasses can override instance methods, getters, and setters. Here’s an example of overriding the Object class method noSuchMethod(), which is called when code attempts to use a nonexistent method or instance variable.

class A {
  // If you do not override noSuchMethod and use a non-existent member, NoSuchMethodError will result.
  void noSuchMethod(Invocation mirror) {
    print('You tried to use a non-existent member:' +
          '${mirror.memberName}'); }}Copy the code

You can use the @override annotation to indicate that you have overridden a member.

class A {
  @override
  void noSuchMethod(Invocation mirror) {
    // ...}}Copy the code

If you use noSuchMethod() to implement every possible getter, setter, and class method, then you can use the @proxy annotation to avoid warnings.

@proxy
class A {
  void noSuchMethod(Invocation mirror) {
    // ...}}Copy the code

For more information about annotations, refer to metadata.

12.7 Enumeration types

An enumeration type, commonly called enumerations or enums, is a special class used to represent a fixed number of constants.

To declare an enumeration type, use the keyword enum:

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

Each value in the enumeration has an index getter method, which returns a position starting from 0 in the enumeration declaration. For example, the first value has an index value of 0 and the second value has an index value of 1.

assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
Copy the code

To get all the values of the enumerated list, use the values constant of the enumeration.

List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
Copy the code

You can use enumerations in switch statements. If e on switch (e) is an enumeration of explicit type, then a warning will pop up if you don’t handle all enumerated values:

// Enumeration test enum LGColor{blue, green, orange} // Each value in the enumeration has an index getter method, which returns a position starting from 0 in the enumeration declaration. For example, the first value has an index value of 0 and the second value has an index value of 1. void enumFunc(){ assert(LGColor.blue.index == 0); assert(LGColor.green.index == 1); assert(LGColor.orange.index == 2); List<LGColor> colors = LGColor.values; print(colors); // [LGColor.blue, LGColor.green, LGColor.orange] LGColor color1 = LGColor.blue; switch(color1) { case LGColor.blue: print("blue"); break; case LGColor.green: print("green"); break; default: print("orange"); }}Copy the code

Enumeration types have the following restrictions

  • You cannot mix or implement an enumeration in a subclass.
  • You cannot explicitly instantiate an enumeration.

For more information, see Dart Language Specification.

13 References

Flutter official documentation: https://flutterchina.club

The Dart official documentation: https://dart.dev/guides/language/language-tour

Geek college team: https://wiki.jikexueyuan.com/project/dart-language-tour/important-concepts.html

The Dart grammar learning: https://www.jianshu.com/p/9e5f4c81cc7d

The Dart syntax: https://www.pipipi.net/dart/dart-syntax.html

Here to recommend a very good iOS dry goods output point: logical iOS technology number. Build iOS prosperity ecology, start from your little love πŸ’–