Fluent -- Dart object oriented

Keywords: Flutter

1. Class and object

In fluent, use the class keyword to declare a class, and use new and constructor to generate an Object. All objects inherit the Object class by default. getter and setter methods are generated by default in dart. Properties and methods are accessed through point syntax. Dart methods do not support overloading. The final decorated attribute must define an initial value.

Declare a class:

class LGPerson {
  String? name;
  int? age;
  final String hobby = 'coding';
  void run() {
    print("name:$name age:$age");
 }
}

Declare an object and method call:

  LGPerson p = LGPerson();
  p.name = 'LS';
  p.age = 18;
  p.run();

In Dart, there is no privatization for the same file. Only in different files can there be private attributes.
Create a new file and add a new LGTeacher class, exposing only the height attribute and printTeacher method.

class LGTeacher {
  String? _name;
  int? _age;
  int? height;

  void _run() {
    print("name:$_name age:$_age");
  }
  void printTeacher() {
   _run();
  }
}

As you can see, private properties and methods cannot be accessed externally, but they can still be accessed if they are class es in the same file.

2. Constructor

After defining a class, the class has a constructor by default. amount to:

LGperson(){}

You can customize the constructor here. If you customize the constructor, the default constructor is invalid.

 LGPerson(int age,String name){
    _name = name;
    _age = age;
  }
  
  LGPerson p = LGPerson(18,"test");

If this is not a private attribute, the attribute and parameter names will be the same:

    name = name;
    age = age;

Here, you can change the name of the parameter or add this. Before the attribute, but it is recommended to use Dart syntax sugar for automatic assignment.

  LGPerson(this.age,this.name);

After using this syntax, the attribute does not need to become Nullability.

class LGPerson {
  String name;
  int age;

  LGPerson(this.age,this.name);
  void run() {
    print("name:$name age:$age");
 }
}

If the attribute is decorated with final, the attribute cannot be changed later.

class can also create named constructors:

  LGPerson.withName(this.name,this.age);
  // call
  LGPerson p2 = LGPerson.withName("kk", 18);

What is the meaning of final? In fact, there is an application scenario, that is, constant objects.
When all the attributes of a class are decorated with final and the constructor is decorated with const, the created object is a constant object. (here, all attributes need to be modified with final, otherwise the constructor will report an error if it is modified with const).

class LGPerson {
  final String name;
  final int age;
  final int height;

  const LGPerson(this.age,this.name,this.height);
//  LGPerson.withName(this.name,this.age);
  void run() {
    print("name:$name age:$age");
 }
}

3. Factory construction & singleton object & initialization list

To create a single instance in Dart is to call yourself in the method. It must not work.

class FactoryClass {
  //A singleton object is required
  static FactoryClass? _instance;
  FactoryClass(){
    _instance ??= FactoryClass();
  }
}

In this case, we need to use the named constructor.

class FactoryClass {
  //A singleton object is required
  static FactoryClass? _instance;
  FactoryClass(){
    _instance ??= FactoryClass._init();
  }

  FactoryClass._init();
}

The constructor in dart does not return an object. If you need to return an object, you need to add factory in front of the method. Here because_ instance's nullability, so you need to force unpacking.

class FactoryClass {
  //A singleton object is required
  static FactoryClass? _instance;
  factory FactoryClass(){
    _instance ??= FactoryClass._init();
    return _instance!;
  }

  FactoryClass._init();
}

The factory method can also be optimized

factory FactoryClass(){
    return _instance ??= FactoryClass._init();
  }
  // even to the extent that
    factory FactoryClass() =>  _instance ??= FactoryClass._init();

This successfully creates a singleton.
In Dart, there is another thing called initialization list. The initialization list will assign a value to the attribute before the constructor runs (note that this cannot be accessed on the right side of the initialization variable).

Initialize list action

  • Assign a value to the final variable
  • Verify the value passed
class Person {
  String name;
  int age;
  final height;

  Person(this.name,this.age,int h):
      height = h, assert(h>=0){
    print('name: $name, age:$age,height:$height');
  }

}

An error will be reported when the incoming height is less than 0.

4. Class method & object operator

In Dart, static attributes and static methods (that is, class methods) are decorated with static.

class StaticClass {
  //Static properties
  static int count = 1;
  // Static method
  static int sum (int a ){
    return a + count;
  }
}

Property assignments and method calls require classes rather than objects.

  StaticClass.count = 10;
  StaticClass.sum(20);

Note that class methods cannot access non static properties, but instance methods can access static properties. This is because static methods are called through class objects. Before class objects are called, instance objects may not exist, so instance properties and methods do not exist, so they cannot be accessed. However, instance methods are accessed through instance objects. Class objects must be loaded after instance objects are created, so static properties and methods can be accessed.

The constant attribute must be decorated with static, or an error will be reported.

  static const int age = 10;

When using an object, the object may be empty. At this time, if you call a method, an error will be reported.

var s1;
s1= StaticClass();
s1 = null;
s1.sum2();

For security reasons, you can add "after" after the object? After the call method, that is:

s1?.sum2()

At this time, if the object is empty, you will get null.

At this time, the type of s1 will change to Object, and an error will be reported when calling the method in the StaticClass class.

Type forced conversion is required at this time.


Or make type judgment.

void staticDemo() {
var s1 = Object();
s1= StaticClass();
if (s1 is StaticClass) {
  s1.total();
}
}

5. Dart's inheritance

In Dart, classes are inherited by singleton. Extend is used to inherit a class. Subclasses will inherit properties and methods other than construction methods.

Create a Person class.

class Person {
  String? name;
  int? age;
  int? _height;
  bool get isFree => _height!< 110;

  run() {
    print("run run run");
  }

Create a Student class that inherits from Person.

class Student extends Person {
  study() {
    print("study study study");
  }
}

Subclasses can access the non private properties and methods of the parent class,

 Student s1 = Student();
  s1.age = 20;
  s1.run();

A subclass can override the method of the parent class, so that the subclass will call the overridden method.

  @override
  // TODO: implement isFree
  bool get isFree => age! < 18;
  @override
  run() {
    // TODO: implement run
   print("student run");
  }

Subclasses automatically inherit the default constructor. If it is a constructor with a name or parameters, it should be called actively.
Parent class

class Person {
  String? name;
  int? age;
  int? _height;
  bool get isFree => _height!< 110;

  run() {
    print("run run run");
  }
  Person(this.age){ print("Person Person Person");}
  Person.init();

}

Subclass (only one can be implemented here):

class Student extends Person {
  Student.init() : super.init();
  Student(int? age) : super(age);

  study() {
    print("study study study");
  }
  @override
  run() {
    // TODO: implement run
   print("student run");
  }
  @override
  // TODO: implement isFree
  bool get isFree => age! < 18;
}

6. Abstract classes and interfaces

Abstract classes are classes that cannot be instantiated. Use abstract to modify them.

Abstract methods can be declared in abstract classes.

abstract class AbstractClass {
  // Abstract methods can only be placed in abstract classes
int sum(int a,int b);

If other classes inherit from abstract classes, they must implement all abstract methods in the abstract class.

class Subclass extends AbstractClass {
  @override
  int sum(int a, int b) {
    return a + b;
  }
}

There is a problem here, so you can only inherit one abstract class. Here, you need to use implements to inherit multiple abstract classes.

class Subclass implements AbstractClass,AbstractClass1 {
  @override
  int sum(int a, int b) {
    return a + b;
  }
}

If implements a class, you need to implement all the properties and methods. Of course, this is not necessary. Generally, it only implements abstract classes.

7. Mix Mixins

Mixin is a class in object-oriented programming language, which provides the implementation of methods. Other classes can access the methods and variables of the mixin class without becoming its subclasses. Mixin's role is to reuse class code in multiple class hierarchies.
Mixins are actually multi inheritance:

class D extends A with B,C {
}

This allows you to call methods in different classes.

  D d  = D();
  d.a();
  d.b();
  d.c();

Here is a question. If the methods in the three classes have the same name, which class will be called? After running, it is found that it is c, that is, the method in the last inherited class will be called.

There is a limitation to mixing, that is, the mixed class cannot implement the constructor, otherwise an error will be reported.

The class' C 'can't be used as a mixin because it extends a class other than' Object '. This is because if the class inherited by C has a constructor with parameters, an error will be reported.


If D does not have its own attributes and methods, then mixing can be abbreviated as.

class D = A with B,C;

8. Operator overloading

In Dart, if you want to compare the size of two classes or other operations, you need to use operator overloading.
If there is no operator overload, the following code will report an error.

void operatorDemo() {
  OperatorClass o1 = OperatorClass(22);
  OperatorClass o2 = OperatorClass(23);
  print(o1 > o2);
}

After overloading the > sign, you can compare the size normally.

class OperatorClass {
  int age;
  OperatorClass(this.age);
bool operator >(OperatorClass other) => this.age > other.age;
}

Posted by daedlus on Fri, 01 Oct 2021 18:41:24 -0700