Dart Functions, Classes and Operators of Flutter Series

Programming languages vary widely, but in the final analysis, the design idea is nothing more than to express and process information.

How Dart represents information has been introduced in the overview of Dart language in the Flutter series. This article describes how Dart processes information.

As a truly object-oriented programming language, Dart abstracts the process of processing information as an object, and functions, classes and operators are the most important means of abstraction.

function

Function is a code snippet used to perform a function independently, and all types in Dart are object types, and functions are no exception, that is, functions are also objects, its type is Function.

void main() {
  Function check = isEmptyStr;
  printStr('',check);
  printStr('Hello World!',check);
}

bool isEmptyStr(String str){//Determine whether a string is null
  return str.isEmpty;
}

void printStr(String str,Function check){//Using check function to judge whether String is null
  if (check(str)) {
    print('$str is null');
  }else {
    print('$str is not null');
  }
}
 is null
Hello World! is not null

In the above code, we first define a function isEmptyStr to determine whether a string is null, and pass it to another printed function printStr, that is, a function can also be defined as a variable, or even passed as a parameter to other functions.

In daily development, we often encounter situations where multiple parameters need to be passed in a function. In this case, Dart is different from other languages such as c, c++, java and so on.

C, c++, java and so on provide overloading of functions, that is, functions with the same name but different parameters. Dart believes that overloading can lead to confusion, so overloading is not supported, but provides optional parameters and optional naming parameters.

Specifically, when declaring a function:

· Add {} to the parameter, specify the call parameter in the form of paramName: value, and then select the named parameter.

· Adding [] to the parameters means that these parameters can be ignored and the parameters can be selected.

Moreover, when defining functions in these two ways, you can also set default values for parameters.

Note: Optional parameters and optional naming parameters can not be used together. Optional parameters and optional naming parameters should be placed after other parameters when declared. The order of declaration is independent when the optional naming parameters are invoked, but the order of declaration is related when the optional parameters are invoked.

void main() {
  _ptionalNamedParameter('Tom',2,sex:'male');
  _ptionalNamedParameter('Tom',2,sex:'male',age:5);
  _ptionalNamedParameter('Tom',2);
  _ptionalNamedParameter('Tom',2,age:25);
  _ptionalNamedParameter('Tom',2,age:18,sex:'female');

  _ptionalParameter('Tom',2,'male');
  _ptionalParameter('Tom',2,'male',5);
  _ptionalParameter('Tom',2);
  //_ Optional Parameter ('Tom', 2,25);//Error
  //_ Optional Parameter ('Tom', 2, 18,'Woman'); //Error
}

bool isNotEmptyStr(String str) {
  return str.isNotEmpty;
}

void printStr(String str,Function check){//Using check function to judge whether String is null
  if (check(str)) {
    print('$str is null');
  }else {
    print('$str is not null');
  }
}

//Optional Named Parameters: Add {} to the parameter when it needs to be defined as an optional named parameter, and set default values to the optional named parameter. It must be defined after other parameters. The order of the parameters is variable and can not be used with the optional parameters.
void _ptionalNamedParameter(String name, int classes, {String sex, int age = 18}) {
  print('_ptionalNamedParameter:name is $name,classes = $classes,sex is $sex,age = $age');
}

//Optional parameters: When it is necessary to define optional parameters, add [], and set default values for optional parameters. It must be defined after other parameters. The order of parameters is not changeable and can not be used with optional named parameters.
void _ptionalParameter(String name, int classes, [String sex = 'male', int age]) {
  print('_ptionalParameter:name is $name,classes = $classes,sex is $sex,age = $age');
}
_ptionalNamedParameter:name is Tom,classes = 2,sex is male,age = 18
_ptionalNamedParameter:name is Tom,classes = 2,sex is male,age = 5
_ptionalNamedParameter:name is Tom,classes = 2,sex is null,age = 18
_ptionalNamedParameter:name is Tom,classes = 2,sex is null,age = 25
_ptionalNamedParameter:name is Tom,classes = 2,sex is female,age = 18
_ptionalParameter:name is Tom,classes = 2,sex is male,age = null
_ptionalParameter:name is Tom,classes = 2,sex is male,age = 5
_ptionalParameter:name is Tom,classes = 2,sex is male,age = null

class

Classes are collections of specific types of data and methods, as well as templates for creating objects.

Class Definition and Initialization

Dart is an object-oriented language. Each object is an instance of a class and inherits from the top-level type Object.

Note: There are no public, protected, private and other keywords in Dart. Instead, as long as variables and methods are declared, they can be used as private by adding "" before them. If no "" is added, the default is public. However, the scope of the "restriction is not class access level, but library (package) access level.

void main() {
    Student student = new Student('Jack', 'male', age:18);
  student.printStudentInfo();
  var s=Student('Tom', 'male');//Omitting new keywords
  s.printStudentInfo();
  Student.studentId = 1;
  Student.printStudentId();
}

class Student {
  String name;
  String sex;
  int age;
  static int studentId = 0;

  //Grammatical sugar, equivalent to in the function body: this.name=name;this.sex=sex;this.age=age;
  Student(this.name, this.sex, {this.age});

  void printStudentInfo() => print('name is $name, sex is $sex, age is $age');

  static void printStudentId() => print('studentId is $studentId');
}
name is Jack, sex is male, age is 18
name is Tom, sex is male, age is null
studentId is 1

In the example above, three member variables are defined and initialized by the constructor grammar sugar; a static member variable is defined, and default values are assigned during initialization, and two methods are defined to print the values of three member variables and one static member variable respectively.

Sometimes the instantiation of a class needs to provide a variety of initialization methods according to the parameters. In addition to optional named parameters and optional parameters, Dart also provides a way to name constructors to make the instantiation process semantically clearer.

Note: Dart supports initialization lists. Before the constructor actually executes, you can assign an instance variable, or even redirect it to another constructor.

void main() {
  Student student = new Student.nameInfo('Tom');
  student.printStudentInfo();
}

class Student {
  String name;
  String sex;
  int age;

  Student(this.name, this.sex) : age = 18; //Initialization variable age

  Student.nameInfo(String name) : this(name, 'male'); //Redirection constructor

  void printStudentInfo() => print('name is $name, sex is $sex, age is $age');
}
name is Tom, sex is male, age is 18

In the example above, there are two constructors in Student: Student and Studnet.nameInfo, where Studnet.nameInfo redirects the initialization of member variables to Student, and Student assigns default values for age in the initialization list.

multiplexing

In object-oriented programming languages, there are generally two ways to incorporate variables and methods of other classes into this class for reuse: inheritance and interface. Dart is also an object-oriented programming language. Therefore, in Dart, the way of reuse is also inheritance and interface.

Inheritance: Subclasses are derived from the parent class, which automatically acquires the member variables and method implementations of the parent class. Subclasses can override constructors and methods as needed.

Interface: Subclasses acquire only the member variable symbols and method symbols of the interface. They need to re-implement the member variables, as well as the declaration and initialization of the method, otherwise the compiler will report errors.

The following examples illustrate the difference between inheritance and interface

void main() {
Android android = new Android();
  android
    ..brandName = 'HUAWEI'
    ..phoneModel = 'P30 Pro'
    ..edition = 'EMUI9.1.1';//Cascade operator, equivalent to android.brandName = Huawei'; android. phoneModel = P30 Pro'; android. edition = EMUI9.1.1';
  android.printInfo();

  IOS ios = new IOS();
  ios
    ..phoneModel = 'iPhone XR'
    ..edition = 'iOS 12';//Cascade operator, equivalent to phone. phoneModel ='iPhone XR'; phone. edition ='iOS 12';
  ios.printInfo();
}

class Phone {
  String phoneModel; //Mobile phone model
  String edition; //Mobile version

  void printInfo() =>
      print('This Phone phoneModel is $phoneModel, and edition is $edition');
}

//Android inherits from Phone
class Android extends Phone {
  String brandName; //brand
  @override
  void printInfo() {
    //Override the implementation of printInfo
    print('This Phone brandName is $brandName, phoneModel is $phoneModel, and edition is $edition');
  }
}

//IOS implements Phone interface
class IOS implements Phone {
  //Membership variables need to be reiterated
  String phoneModel;
  String edition;
  //Method needs to be reimplemented and initialized
  void printInfo() => print('This is IOS Phone, phoneModel is $phoneModel, and edition is $edition');
}
This Phone brandName is HUAWEI, phoneModel is P30 Pro, and edition is EMUI9.1.1
This is IOS Phone, phoneModel is iPhone XR, and edition is iOS 12

The above code adds member variables to Android by inheriting Phone, and overrides the implementation of printInfo (); IOS overrides Phone's variable definition and method implementation by interface implementation; and from the above code, it can be seen that interface does not bring us practical benefits.

Note: Dart, like other programming languages, does not support multiple inheritances

In fact, in addition to inheritance and interface, Dart also provides us with another mechanism for class reuse, Mixin: Mixing encourages code reuse, which can be considered an interface with implementation methods.

To use mix-in, you just need the with keyword.

void main() {
  IOS ios = new IOS();
  ios
    ..phoneModel = 'iPhone XR'
    ..edition = 'iOS 12';//Cascade operator, equivalent to phone. phoneModel ='iPhone XR'; phone. edition ='iOS 12';
  ios.printInfo();
}

class Phone {
  String phoneModel; //Mobile phone model
  String edition; //Mobile version

  void printInfo() =>
      print('This Phone phoneModel is $phoneModel, and edition is $edition');
}

class IOS with Phone {}
This Phone phoneModel is iPhone XR, and edition is iOS 12

As can be seen from the example above: by mixing, variables and methods in other classes can be used in a non-inheritance way in one class, that is, by mixing, the single inheritance problem can be solved.

operator

Dart provides several additional operators, in addition to operators in most other programming languages, to simplify the handling of null cases of variable instances.

Operator: Suppose there is a printInfo() method in the Phone class. Phone is a possible instance of null in the Phone class. The security method of calling a member method can be simplified to phone.?printInfo(), which means that if the phone is null, the printInfo() method will be skipped.

Operator: If the variable a is null, then assign value to a, which is responsible for skipping. a??=value

Operator: If A is not null, return the value of a, otherwise return the value of b. a??b

void main() {
  Phone phone;
  phone?.printInfo();//Because the phone is null, the printInfo() method is not executed
  Test();
}

class Phone {
  String phoneModel; //Mobile phone model
  String edition; //Mobile version

  void printInfo() =>
      print('This Phone phoneModel is $phoneModel, and edition is $edition');
}

void Test(){
  int age;
  print('age=$age');
  print('age=${age??16}');//?? Operator, age null, return 16
  age??=18;//??= Operator, age is null, assign 18 to age.
  print('age=$age');
  print('age=${age??20}');//Operator, age is not null, return 18
  age??=22;//??= Operator, age is not null, return 18
  print('age=$age');
}
age=null
age=16
age=18
age=18
age=18

In Dart, everything is an object, and the join operator is part of the object membership method.

For system operators, only basic data types and types provided in standard libraries are generally supported. For user-defined classes, if you want to support basic operations, such as comparing sizes, adding and subtracting, you need the user to define the specific implementation of this operator.

Dart provides an operator override mechanism. We can not only override methods, but also override or customize operators.

Operator is Dart's keyword, used with operators to represent a class member operator method

void main() {
  Vector v = new Vector(5, 3);
  Vector v2 = new Vector(1, 2);
  Vector v3 = new Vector(4, 1);
  Vector v4 = v - v2;
  print('x = ${v4.x}, y = ${v4.y}');
  print(v3 == (v - v2));
}

class Vector {
  num x, y;

  Vector(this.x, this.y);

  //Custom subtraction operator
  Vector operator -(Vector v) {
    return Vector(x - v.x, y - v.y);
  }

  //Override the Equality Operator
  bool operator ==(dynamic v) {
    return (x == v.x && y == v.y);
  }
}
x = 4, y = 1
true

The article has been updated to Wechat Public Number synchronously. Welcome to pay attention to it.

Keywords: Android iOS Programming Mobile

Added by bruceg on Sun, 25 Aug 2019 12:06:08 +0300