preface

Dart is a programming language designed for Java learners. Dart is similar to Swift in some of its syntax. It is safe to say that Google has put a lot of thought into creating flutter across platforms. After all, a native of Java and ios is currently the latest and most popular swift

In terms of language, Java and Swift as long as you know one, the hand is as simple as drinking water, follow me to learn it again, after learning the rest is actual combat

Dart_demo – this example can be downloaded from vscode and run by right clicking the code (note: run from the file’s main function).

Study reference address

Ps: Some people may say, you are not according to the reference address, after learning a time, their own example of a simple translation is over? I would say this is part of my learning to understand and remember, and I can see how easy it is to get started with the Dart language

Dart programming language

Importing a library

To import a library, use “import”, followed by [DART: library name]

In addition, for imported files, the relative location of the file is located according to the current path

./ : Returns the current file directory

. / : Returns the previous directory

// To use the library, you must write to the top
import 'dart:async';
import 'dart:html';
// Import the math library
import 'dart:math';
// Import the built-in file, import a project file, using a relative path
import './4class.dart'; 
Copy the code

Constants and variables

Variables are var modifiers, and many languages use let to modify constants. Final is the same as let. You can assign a value to a variable once, and const means read-only

In addition, dart does not specify the type of the variable when declaring the object. The system automatically deduces the actual type based on the type at the time of creation.

Ps: Different from JS, JS var has the effect of variable promotion. Let is equivalent to declaring ordinary local variables, where var declares a common variable

// Assign a string attribute
const readonlyName = "I'm a read-only constant."; // used during editing, similar to let in swift

// Final finalName = "I can only be assigned once "; // Only chairs can be assigned
final finalName; // Can only be assigned once and cannot be assigned thereafter, as in let in swift
finalName = "I can only be assigned once.";

// static const sreadonlyName = "I am a read-only class attribute, can only be used in classes ";
var name = "I'm a variable that can be changed."; / / variable
name = "My content has been updated.";
Copy the code

Digital number

Here the number is also an object, and JS similar, the number has its own object methods, can carry out some mathematical operations

Ps: the type of numbers are all lowercase ha, and other different, the feeling may be another person wrote πŸ˜‚

// Numbers, you can use the usual Math function
var num1 = 10; // Type inference, actually int type
var num2 = 10.2; // Type inference, actually double

// Numbers can use abs(), ceil(), floor(), etc. It also supports the common four operations, shift, and, or, not, xOR, etc
// You can also use the math library 'dart:math';
var num3 = num1 | num1 & num1 & num1;
var numa = num2.abs();
var numc = num2.ceil();
var numf = num2.floor();
var nump = pow(num2, num1); // The method of math library

/ / bool type
var boolNum = true;
boolNum = false;
Copy the code

String String

The string class is also an object, and you can concatenate strings as in other languages with + or ${}, even with the same operation names for some strings, as shown below

var str = 'I'm a normal string';
var str1 = "I'm an undifferentiated double quoted string.";

var str2 = str + str1; // Concatenates a string

// A string of multiple lines can be concatenated using three single quotes or three double quotes
var str3 = ' '' 'sfasdf' '123123'
'' ';
str3 = """ sfasdf 123123 """;

Internal strings preceded by r will not be escaped
var rstr = r'1212313 \n 123123';

// Concatenate other variables in the string, wrapping variable contents with ${}
var spitStr = ${str.length}, str1 :${str1};

// Get substring 1-2, starting from 1, 3-1=2 strings
str.substring(1.3);

// Split strings into arrays, common in other languages
str.split('δΈ€');

// Whether to contain a substring
final result = str.contains(str1);

// Find the position of the substring
str.indexOf(str1);

// Convert to case
str.toLowerCase();
str.toUpperCase();
Copy the code

String numbers convert to each other

Strings, numbers are more commonly converted, as shown below

ToString is a method that basically exists in each object and can be converted into a string. In some network data, it is required to be called basically for security

It’s also common to keep the decimal point, and to have specific methods to avoid writing your own logic

var num1 = 10;
var num11 = 10.21312893192783;
var str1 = "10.2";

// Number conversion string
var num2 = int.parse(str1);
var num3 = double.parse(str1);

// The string is converted to a number
var str2 = num1.toString();
var str3 = num1.toStringAsFixed(2); // Keep two decimal places
Copy the code

The array List

Arrays in this case are of type List (not Array), and it has to be said that the most common collection in use is arrays, which are ordered linear collections

// Create an empty array. Default is any type. Constructor is not recommended
var list = [];
var list1 = <int>[]; // Create an array of type int only

// Add elements
list.add(1);
list.add("asfsdf");
list.add("123");
list.addAll(list1); // Add all the elements in the array

// Deletes the specified element, or the specified index element
list.remove('123');
list.removeAt(0);

// Insert the element
list.insert(1."Insert element");

// Get the number
list.length;

// Internal sort
list.sort((a, b) = > a > b);

// Concatenate array elements into strings using delimiters
var str = list.join('; ');

list.reversed; // set the antiarray

// Forin group (recommended)
for (var item in list) {
}
// Internal use is also forin
list.forEach((element) {
});
var newList = list.map((e) = > {
  e = e + "La la la la"
});
Copy the code

Hash table Set

Set is a hash table, a need not Set, the hash value was generated according to the content, use hash value as the index to get the data information, internal specific performance is a hash table, table tree, hash table tree table, or other, don’t know, it is said that some in the use of hash table at the same time, adopt the way of dichotomy query, gave up the red-black tree meter etc.)

Features: Slow write speed, fast read speed, does not store duplicate data

// Create a set
var sets = {};
// create using the Set constructor
var sets1 = Set(a);var sets2 = Set<String> ();// Create a set with a value
var set = {1.2.3.'ha ha'.'now!'};
var set1 = <int>{1.2.3}; // Create a Set of the specified type

set.add(3);
set.add('ha ha');

// Remove an element
set.remove(3);

// If there is an element in it, fetching it is not necessary
set.contains(3);

set.length; // Get the number

// Go through the collection (recommended)
for (var item in set) {
}
// Internal use is also forin
set.forEach((element) {
});
Copy the code

Key-value Specifies the hash table Map

Map is also a hash table, but it uses key to generate hash values, store information such as value, namely the form of key-value hash table, implementation is similar to Set, internal specific performance is a hash table, tree table, hash table tree table combination or other, do not know (it is said that some in the use of hash table at the same time, using dichotomy query, Abandoned red-black tree equivalence tables)

// Create an empty Map. {} represents an empty Set
varmap = <String, String>{}; Var map1 = Map<int, String>(); Var map2 = {"key1": 'ha ha ', "key2": "la la"}; // Assign and get map["123"] = "la la "; var content = map["123"]; Map1 [1] = "ha-ha "; var content2 = map1[10]; // Whether it contains an element key map.containsKey("key"); ForEach ((key, value) {}) for (var item in map.keys) {}Copy the code

The value can be dynamic or Object

Dynamic represents any type and can be used as a generic type (in practice, it is recommended that this type not be used at all and is prone to hidden bugs), like any in typescript and Object in Java

Like Dynamic, Object can represent all Object types. As far as we know, String, number, etc are all Object types (we haven’t encountered other non-object types yet).

Id and NSObject are different in ios, where ints, chars, and so on are non-object types and therefore cannot be replaced

Basic flow statement

Basic flow statements include the common if else, for, while, do while, and switch control statements

var a = 10;
var b = 20;
var c = "a";
var d = "b";

if (c == d ) {
// The condition is met
}else {
// The condition is not met
}

//for loop traversal
for(var i = 0; i < 10; i++) {
print("Ha ha ha.");
}

//for in traverses the collection quickly
var list = [];
for(final item in list ) {
print(item);
}
// Inside is for in
list.forEach((element) {
print(element);
});

// Go first control statement
while (a++ > b) {
print("A is not greater than B");
};

// go to internal statement and then go to control
do {
print("A is not greater than B");
} while(a++ > b);


var command = 'open'; // On, open, off, close, other
switch(command) {
case 'on':
case 'open': 
  print('The door was open');
  break;
case 'off':
case 'close': 
  print('The door is closed');
  break;
default: 
  print('The door may have been broken. I don't know if it's open or closed.');
  break;
}
Copy the code

Exception catch try catch

When writing code, it is inevitable to encounter irresistible factors. For example, some old apis throw an exception in use, or a failed network request may throw a failed exception. This can be solved by try-catch, or by the on keyword if you want to catch a specified exception

void test9(int num) {
  if (num > 10) throw FormatException("Num cannot be greater than 10");
}
void test10() {
  try {
    test9(12);
  }catch(e) {
    print(${e.tostring ()} ${e.tostring ()});
  }

  try {
    test9(12);
  }on FormatException {
    print("Only one class is caught based on the type of exception thrown.");
  }catch(e) {
    print("Catch the remaining types");
  }finally {
    // Execute regardless of exception}}Copy the code

The timer

Timer in the usual development of the use in the common, here is directly introduced first

The following is a delay Timer and an interval Timer written using Timer

Note: The interval timer should be released at an appropriate time after being used, otherwise it will continue to be executed (the appropriate time can be, a certain function is completed, this module is launched, etc.)

// A timer that will callback only once
Timer(Duration(seconds: 5), () {
// Run a 5s timer
});

// A timer that calls back multiple times
var num = 0;
Timer.periodic(Duration(seconds: 5), (timer) { 
  if (num++ > 10) {
    timer.cancel(); // Cancel the timer
  }
  print(num);
});
Copy the code

function

Definition of a function

The function definition is similar to Java, as shown below

// No parameter, no return value function
void getUserInfo(){}// Simplifies the return value effect without parameters
getUserInfo1(){}// Function with parameters
getUserInfoByToken(String token){}// Parameter belt? Function, can be understood as an optional argument, in addition to the specified type, can be passed NULL
getUserInfoByToken1(String? token){}// parameter with return value
List getUserInfiByToken1(String token) {
  return [];
}
// Set the return type
List<String> getUserInfiByToken2(String token) {
  return ["La la la la"];
}
Copy the code

Closures (anonymous functions)

In development, instead of just using normal functions, sometimes using closure functions is less work and easier to use, both in passing arguments and in calling

// No arguments, no return value closure function
var block = () {
print(123);
};
block();

// parameter with return value
var block1 = (num) {
return num + 1;
};
var result = block1(10);
print(result);


// With arrows, simplified operation, somewhat compatible with JS arrow function meaning
var block2 = (num) = > pow(num, 2);
var result2 = block2(14);
print(result2);

var block3 = (str) = > {
print("${STR}")}; block3("Aiya!");
Copy the code

Closures, functions as arguments (both are the same)

When a closure function is a parameter, it can be as normal as a function, as long as it is of a glance type. It is passed a function pointer or a closure pointer

As shown in the following, we can demonstrate the transfer mode between functions with no parameters, functions with parameters, closures, and ordinary functions. A declaration that represents an optional type is passed in

? Is an optional type, representing the specified type or null, such as double? Represents a floating point number or NULL

// A normal function with no parameters
getUserInfo(){}// Pass in a parameterless closure or a normal function
requestUser(void completed()) {
  Timer(Duration(seconds: 2), () {
    completed();
  });
}
// Pass the closure argument, plus? The closure parameter name is in the middle, so? To the end)
requestUserTokenByCompleted(void completed(String? userToken)?) {
  Timer(Duration(seconds: 2), () {
    if(completed ! =null) {
      completed(DateTime.now().microsecondsSinceEpoch % 5 > 2 ? 'abc' : null); }}); }// The standard writing of flutter has been improved
requestUser(Function() completed) {
  Timer(Duration(seconds: 2), () {
    completed();
  });
}
// Optional case with parameters
requestUserTokenByCompleted(Function(String? userToken)? completed) {
  Timer(Duration(seconds: 2), () {
    if(completed ! =null) {
      completed(DateTime.now().microsecondsSinceEpoch % 5 > 2 ? 'abc' : null); }}); }// Closure functions
void main() {
    // Call the no-argument closure function
    requestUser(() {
      print("Called a parameterless closure function.");
    });
    // The requestUser callback is now in the getUserInfo normal function
    requestUser(getUserInfo);
    
    // Call the parameterized closure function
    requestUserTokenByCompleted((token) {
      print(${token} = ${token});
    });

    requestUserTokenByCompleted((token) {
      print(${token} = ${token});
    });

    requestUserTokenByCompleted(null);
}
Copy the code

Function types with same names: When passing functions or closure functions, the type can sometimes be very cumbersome. You can rename the simplified parameter type to be the same as the normal type, such as double


// Rename, or declare a closure type with a different name than usual between the return value and the parameter, as well as the parameter
typedef void blockType(int num);

// Call it like a normal variable
test(blockType block) {
    block(2);
}
Copy the code

The operator

The assignment operator

Assignment operators are common in many languages, such as?? = * = / = + = – = % = & = | = ~ = < < = > > = > > > =

& = : (bitwise and assignment) | = : (Ann by assignment)! = : (in a draw against assignment) < < = : (in a left shift assignment) > > = : (according to the arithmetic moves to the right, the front position zero padding) > > > = : (bitwise logical moves to the right, the front position to fill the sign bit)

Here are some of the less common ones

/ /??
var a = b ?? c // Return b if b exists, otherwise return c

/ /?? =b ?? = value// If b is present, b remains unchanged, and if b is empty, then value is given to b
Copy the code

Relational operator

Relational operators, such as as, IS, is! I won’t say much about whether it’s the same or not

As: a type conversion that can be used to convert a type, for example, to a subclass of a conversion that declares a parent class.

Is: checks whether a class is a class or a subclass of it, returning true if it is, false otherwise; Is T is also true if a class implements an interface T

//as, is, is!
// There are two classes of Student that inherit from Person

// Student inherits from Person, but does not report an error at compile time
var p = new Person();
var a1 = p as Student; //
a1.getName(); // If p does not actually have Student's getName method, then an error is reported

//as
// The type of the declaration at compile time will not be reported
// An error may still be reported if the actual class is not called
When used, an object is declared as a polymorphic or generic type, which can be converted to the actual type using as

//is 
// Check whether a class is a class or a subclass of it, true if it is, false otherwise
// If a class implements an interface T, then is T is also true
Copy the code

Cascade operator

. ,? . Is the two keywords of the cascade operator, the former is the default call, the latter is optional call, empty is not called

/ /.. Or? . You can omit the call and simplify calling a method or variable multiple times
// If the object exists, use..
varpaint = Paint() .. color = Colors.black .. strokeCap = StrokeCap.round .. strokeWidth =5.0;

/ / equivalent to

var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;


// Teammate some objects may not exist in the case, use? . +..
querySelector('#confirm') // Get an object.? . text ='Confirm' // Use its members.
    ..classes.add('important')
    ..onClick.listen((e) = > window.alert('Confirmed! '));

/ / equivalent to

var button = querySelector('#confirm'); button? .text ='Confirm'; button? .classes.add('important'); button? .onClick.listen((e) = > window.alert('Confirmed! '));
Copy the code

Async supports async await

Async and await are common

When an asynchronous method encounters an await object, the asynchronous method is blocked, stored in a Future object, queued to delay execution, and then cut out the function to continue execution (note: Not skip await continue to perform this function, but returned to continue to perform at the next higher level), and then continue to execute, encounters await modified continue to block stored in the queue, until after other methods has been completed, and then start to develop Future delays in the content of the block in the queue, thus simulating the asynchronous effect (due to flutter is single-threaded, And according to the effect guess, the general principle should be similar, does not affect the use)

Ps: Whether the execution of the block is actually open multithreading can be checked by yourself. It may only simulate asynchronous logic, similar to the operating system switching the CPU to execute the task segment time, so that the task can get a response

A Future is similar to a JS Promise, but without reject, it returns a Future argument by default. Arguments can be obtained either with await or then, with await provided that the current function supports async, while then does not

Why do you say that, when you see the test results, you can guess a little bit

// Declare an asynchronous method
Future<bool> simulateOperate() async {
  // Suppose this has some very time-consuming operation logic, such as collating local data
  var num = 0;
  for(var i = 0; i < 10000000; i++) {
    num++;
  }
  print('My asynchronous task is done --${num}');
  return true;
}

// Perform a synchronous method call and find that the asynchronous task is performing properly
void test() {
  print('Start test synchronization method');
  // The result of the asynchronous task is ignored here
  // No await, actually block the execution of subsequent tasks, so it is understood that I am synchronous execution
  var res = simulateOperate();
  print(${res} = ${res});
}

// We must use await with async functions to await the result of an asynchronous task, and omit the Future if no value is returned
testAwait2() async {
  print('Enable testAwait2 asynchronous method');
  var res = await simulateOperate(); // It returns true
  print('I'm testAwait2 async method, done: ${res}');
}

// The same as above, except that then is used
testAwait2() {
    print('Enable testAwait2 asynchronous method');
    simulateOperate().then((res) {
        print('I'm testAwait2 async method, done: ${res}'); })}void main() {
  print("General mission begins.");
  test();
  print("First test completed.");
  testAwait2();
  print("Second test completed.");
}
Copy the code

The following information is displayed

// Print the result
// I/ FLUTTER (5664): The overall task begins
// I/ FLUTTER (5664): enable the test synchronization method
// I/ FLUTTER (5664): my asynchronous task has finished --1000000000
// I/flutter (5664): I/flutter (5664): I/flutter (5664): I/flutter (5664):
// I/ FLUTTER (5664): First test completed
// I/ FLUTTER (5664): enable the testAwait2 asynchronous method
// I/ FLUTTER (5664): my asynchronous task has finished --1000000000
// I/ FLUTTER (5664): Second test completed
// I/flutter (5664): I am testAwait2 asynchronous method, complete: true
Copy the code

Declare async function when you need to await it, otherwise it will have no effect and add code

The enumeration

Generally used in type judgment, it can better number type, can friendly judge the meaning of the type, improve code readability, and use with switch is more convenient, but also can give better hints

/ / the enumeration
// call, you can use swift as described earlier to implement different cases, of course if else can also be used
enum Level {
  firstLevel,
  secondLevel,
  thirdLevel,
  maxLevel
}

// Use of enumeration
Level.firstLevel
Copy the code

Classes and objects

A class is an abstraction of an object, and an object is a carrier of a class. An object can be understood as a template specification of an object, from which similar objects can be produced.

Declaration of a class

Declare a Class using the Class keyword

// Use the class keyword to declare a class called Person, which is a partial abstraction of people
class Person {
   String name = ' ';
   int age = 0;
   
   Person(this.name, this.age);
}
// personA and personA are defined by Person. These two persons are objects
var personA = Person("Zhang".20);
var personB = Person("Bill".21);
Copy the code

attribute

Attribute declaration requires initial values by default, otherwise optional? , the optional type defaults to null

class Point {
  double x = 0;
  double y = 0;
  // double? x, y; // Multiple statements can be made consecutively or assigned
  // double x = 0, y = 0;
  final double z; // Attributes can only be assigned once
}
Copy the code

The constructor

Constructors can be created in several ways, as described below (note that only one constructor can be created, except for named ones). Destructors do not see πŸ˜‚

Note: If you do not write the constructor, there is a default constructor with no arguments (that is why the system requires default values for all arguments; if you override the constructor, the initial value must be necessary).

class Point {
  double x = 0;
  double y = 0;
  final double z; // Attributes can only be assigned onceSo the general constructor would write it this wayPoint(double? x, doubel, y) {
    this.x = x;
    this.y = y;
  }

  // The constructor cannot be overridden, only its own
  Point(this.x, this.y, this.z); // constructor

  // When assigning, the rest can be assigned in this way
  Point(this.x, this.y): z = 20;

  // name constructor
  [class name].[method name]
  // If the constructor does not pass arguments, or if it misses, you need to add: assign to the remaining arguments, as shown below
  Point.origin(): x = 0, y = 0, z = 0;
  // equivalent to the following
  Point.origin(this.x, this.y, this.z);

  //factory Factory mode
  // Use the named constructor to define a constructor to assign a value to
  Point.internal(this.x, this.y): z = 0;
  // Use the default properties to turn on the construction factory for the default constructor
  factory Point(String key) {
    var pointList = pointMap[key];
    if (pointList == null) {
      return new Point.internal(0.0);
    }
    return Point.internal(pointList[0], pointList[1]); }}Copy the code

The invocation of various classes is shown below

void main() {
  var point0 = Point(0.0.0); // Use the constructor normally
  var point1 = Point.internal(10.10); // name constructor
  
  var point = Point("1010"); // Call the factory constructor to initialize
  point.printPoint(); // Call the object method
  Point.sPrintPoint();// Call the object method
}
Copy the code

A static method

To declare a static method in a class, use the static keyword so that the method can be called by the class name

Note: In static methods, this does not refer to a class, so static methods cannot use this

class Point {
  // Declare a function, which is not covered here
  printPoint() {
    print("point");
  }

  // It can be understood as a class method and needs to be called by the class name, but unlike other languages, it cannot have the same name as an object method
  static sPrintPoint() {
    // Note that static methods do not use this to call methods of the same type as in other languages
    print("point");
    Point.sPrintPoint2(); // Can't use this.sprintpoint2 ()
  }
  static sPrintPoint2(){}}Copy the code

Rewriting operator

By overriding operators, you can make a class have the same operations as a number

Statement: Point operator Symbol + parameter + implementation

class Point {
  double x = 0;
  double y = 0;
  
  // Override the operator by passing in a variable to the right of the operator
  Point operator +(Point value) = > Point.origin(x + value.x, y + value.y);
  Point operator -(Point value) = > Point.origin(x - value.x, y - value.y);
}
Copy the code

Setter and Getter

Setters and getters are very different from ios, where you actually override the Setter and Getter methods for properties, but you just call them like properties

It is generally used according to the current attribute, virtual new attribute, usually use is not necessary (can also make a singleton of similar attributes)

The definition is implemented with the get set keyword, as shown below

It can only modify method names with set and GET, which can be assigned and obtained like method properties, but do not override already-declared property fields, and cannot have the same namevar instance = Rectangle(1.2.3.4);
class Rectangle {
  double left, top, width, height;

  // You can use the static method to create a singleton
  static Rectangle get shared => instance;

  // Set and get can be used as set and get
  // Set a right-sided property
  double get right => width + left;
  set right(double value) = >left = value - width;
}
Copy the code

Abstract methods (interfaces and implementations)

An abstract method, decorated with the abstract keyword, is an interface, usually implemented as an interface into similar classes

A class implements an interface, which is separated by the implements keyword

// Abstract method
// It cannot create an instance, and the methods defined internally must be abstract
abstract class AbstractClass {
  speak(); 
}
abstract class AbstractClass1 {
  talk();
}
// Implement the interface
// By implementing interfaces, it is possible to implement unified scheduling for different classes, just like polymorphism
class Children implements AbstractClass {
  @override
  speak() {
    print("嘀嘀嘀"); }}class Person implements AbstractClass {
  @override
  speak() {
    print("I don't just hum, I ha-ha-ha."); }}Copy the code

By declaring a variable type as an interface type, it can be uniformly scheduled by classes that follow the interface, as shown below

speakForAll(AbstractClass p) {
  p.speak();
}
testSpeak() {
  var chi = Children();
  var per = Person();
  speakForAll(chi);
  speakForAll(per);
}
Copy the code

inheritance

With the extends keyword, you can inherit a class. The inherited class is called a parent or superclass, and its successors are called subclasses or derived classes

// It is possible to define an interface within a class by inheriting it
// Therefore, interfaces defined by inheritance are also called implicit interfaces
class ParentClass {
  ParentClass();

  void sayHello() {
    print("hello"); }}// extends
class SubClass extends ParentClass {
  SubClass();

  @override
  void sayHello() {
    // super.sayHello(); // The superclass method can be called by super
    print("I can't sayHello"); }}Copy the code

A parent type can be used to declare a subclass variable, which is a type of polymorphism

A parent class (superclass) is inherited and generates multiple species, which is also polymorphic. For example, defining an animal class as a parent class and subclasses as cattle, horses, snakes and sheep is also polymorphic

// This is one of the uses of polymorphism
test(ParentClass p) {
    p.sayHello();
}
var sub = SubClass();
test(sub)

// This is also polymorphic. Subclasses are also called derived classes
class Animal {
    speak() {
        print("I can talk."); }}class Dog extends Animal {
    @override
    speak() {
        print(Woof woof woof); }}class sheep extends Animal {
    @override
    speak() {
        print("Baa baa"); }}Copy the code

Inherit and implement abstract interfaces

Inheritance and implementation interfaces do not conflict, and interfaces can be implemented at the same time, through, separated, as shown below

// Inherit and implement abstract interfaces. Multiple abstract interfaces can be implemented simultaneously
class B extends A implements AbstractClass.AbstractClass1 {
  @override
  speak() {
    print("I don't just hum, I ha-ha-ha.");
  }
  
  @override
  talk() {
    print('I'm not just ringing, I'm ringing.'); }}Copy the code

Class extend the extension

You can extend a new property or method from an existing class, the parent class of the extension, the child class of the extension, and vice versa

Usage: Extension + extension + on + name of the extended class

Ps: Some people may feel that the extension is not necessary, but the actual extension can be used as a tag name to distinguish the different functions of the extension and make it easier to read

extension Employee on SubClass {
  void work() {
    print("I can work.");
  }
}
extension Sleep on ParentClass {
  void sleep() {
    print("I rested."); }}Copy the code

Multiple inheritance maxin

The use of maxin modified parent class, can let the heirs at the same time to achieve the effect of multiple inheritance

A general class extends only one parent class. Multiple inheritance can be implemented by declaring a class with + maxin, and maxin-modified classes can only be inherited using the with keyword

Declaration of multiple inherited parent classes: maxin + class name

Class… + with + maxin class

The advantages of multiple inheritance are that you can concatenate multiple small function classes into one large class, which is very flexible (compared to extensions), and the drawbacks are obvious. Too flexible, the code is not easy to control, and the readability is reduced

Note: other languages (except C++) replace it with interfaces, protocols, extensions, etc. Extensions are similar, but they are for fixed classes

// Define a class for playing games
mixin Player {
  bool canPlayWangzhe = false;
  bool canPlaychiji = false;

  playGames() {
    print('Here, I'm a gamer');
  }

// Select * from 'A'; // Select * from 'with'
class maxinTestClass extends A with Player {}Copy the code
Multiple inheritance type constraints

Type constraint: when a maxin modified class is more than inherited, it can be more than inherited only if it inherits the specified class

Declarations are inherited from multiple parent classes: maxin + class name + on + is constrained to the class name

// Define a class for playing games
mixin Player {
  bool canPlayWangzhe = false;
  bool canPlaychiji = false;

  playGames() {
    print('Here, I'm a gamer'); }}// Define a class that can only be inherited from B classes, multiple inheritance
mixin stu on B {
  study() {
    print('I'm a student. I have to learn.'); }}// Select * from A; // Select * from A
// Stu cannot be inherited from A
class maxinTestClass extends A with Player {}// Select * from Stu and player
class maxinConstraintTest extends B with Player.stu {}Copy the code

The generic

A generic type can be defined by a type name (usually T, or depending on the scenario), and can refer to a specified type (the generic type passed in by the user).

Example: List collection, which can have a specified type and then add all elements of that type only (this modifies a class using generics)

var list = <int>[];
       
        
         
          
         
        
       
      
Copy the code
Modify classes using generics

By following the class name with a

form, you can specify a generic type that can be used to unify parameter types

// Define a stack and define a generic type (named T) to replace the type of nodes in it
class Stack<T> {
  List<T> container = [];
  // Pass in arguments of type T
  push(T element){ container.add(element); }}Copy the code

The calls are as follows: one passes in String, that is, T is String, and the other passes in int, that is, T is int

var stack = Stack<String> (); stack.push("Ha ha");
var stack2 = Stack<int>();
stack2.push(2);
Copy the code
Use generic modification functions

In development, it is possible to encapsulate a processing method that supports many types, such as stuffing a collection, exchanging two parameter contents, and so on

// May encapsulate one that supports multiple types of processing methods
// Simply using a generic method has a type constraint called extends
class handlerClass {
  static pushByList<T>(List<T> list, T object) {
    list.add(object);
    //debug can print the actual type string of the runtime
    // print(object.runtimeType.toString());}}Copy the code
Generic constraint

Extends constrains a generic, so it can also be understood that the generic inherits some class, interface

// What if you want to restrict the types that generics can use like multiple inheritance
// Use extends to restrict type int or a subclass of it, as shown below
class StrStack<T extends String> {
  List<T> container = [];
  // Pass in arguments of type T
  push(T element){ container.add(element); }}// The generic constraint defines a function
class handlerClass {
  static pushByList<T extends String>(List<T> list, T str) { list.add(str); }}Copy the code

The call method is shown below

var stack = StrStack<String> (); stack.push("Ha ha");
// var stack2 = StrStack
      
       (); This is an error, and the function looks the same
      

var list = <String> []; handlerClass.pushByList(list,"Ha ha ha.");
Copy the code

The last

Following this article, I learned and expanded again, and the benefits are very shallow, which is also a commonly used content record. If you see it again, follow it again, I believe you will also gain something, at least not familiar with dart is not πŸ˜‚