[Dart Grammar] Chapter 8: Classes

kind

class definition

//Define a class of Person
class Person {
  //Attributes
  String userName = 'Tobu';
  int age = 25;
  String blogAdress = 'https://www.cnblogs.com/TobuTobu';
  String userInfo = 'Hello, I am Tobu, A mobile developer';

  //method
  _printInfo() {
    print('Username: $userName\n User age: $age\n blog address: $blogAdress\n User Profile: $userInfo');
  }
}

instantiation of the class

//instantiate class
Person p = new Person();
//Attributes of the referenced class
print(p.userName);
print(p.age);
print(p.blogAdress);
print(p.userInfo);
print('------------------------------------------');
//method of reference class
p._printInfo();
/*
Tobu
25
https://www.cnblogs.com/TobuTobu
Hello, I am Tobu, A mobile developer
------------------------------------------
Username: Tobu
 User age: 25
 Blog address: https://www.cnblogs.com/TobuTobu
 User Profile: Hello, I am Tobu, A mobile developer
*/

Constructor

default constructor

//The contents of the constructor are automatically triggered when instantiated
class Person {
  //Attributes
  String userName;
  int age;
  String blogAdress;

  //default constructor
  Person(this.userName, this.age, this.blogAdress);
}
//-----------------------------------------------------
//declare variable
String userName = 'Tobu';
int age = 25;
String blogAdress = 'https://www.cnblogs.com/TobuTobu';
//instantiate class
Person p = new Person(userName, age, blogAdress);
print(p.userName);
print(p.age);
print(p.blogAdress);
/*
Tobu
25
https://www.cnblogs.com/TobuTobu
*/

named constructor

class Person {
    //Attributes
    String blogAdress;
    //named constructor
    Person.blogAdress(this.blogAdress) {
        print('My blog address is: $blogAdress');
    }
}

main(List<String> args) {
  //declare variable
  String blogAdress = 'https://www.cnblogs.com/TobuTobu';
  //instantiate class
  Person p1 = new Person.blogAdress(blogAdress);
}
/*
My blog address is: https://www.cnblogs.com/TobuTobu
*/

getter s and setter s

getter

//useless getter
main(List<String> args) {
    Area a = new Area(10, 20);
    print(a._getArea());
}

class Area {
    double height;
    double width;
    Area(this.height, this.width);
    _getArea() {
        return height * width;
    }
}

//Using getter, access _getArea directly by accessing properties
main(List<String> args) {
    Area a = new Area(10, 20);
    print(a._getArea);//changed
}

class Area {
    double height;
    double width;
    Area(this.height, this.width);
    get _getArea {//changed
        return height * width;
    }
}

setter

main(List<String> args) {
    Area a = new Area(10, 20);
    a._setHeight = 5.0;//Modify height
    print(a._getArea);
}

class Area {
    double height;
    double width;
    Area(this.height, this.width);
    get _getArea {
        return height * width;
    }

    set _setHeight(value) {
        this.height = value;
    }
}

Static members and static methods

main(List<String> args) {
    //Non-static methods need to instantiate the class
    var p = new Person();
    p._printInfo();

    //Static methods do not need to instantiate the class
    Person._show();
}

class Person {
    static String name = 'Tobu'; //static properties
    int age = 25; //non-static properties

    //Static methods cannot call non-static members (properties and methods)
    static _show() {
        print(name);
    }

    //Non-static methods can access both static and non-static members
    _printInfo() {
        print(name); //Accessing static properties cannot use this
        print(this.age); //Access non-static properties
        _show();//access static methods
    }
}

/*Summarize:
1: static property + static method = static member | non-static property + non-static method = non-static member
2: Static methods cannot call non-static members (properties and methods)
3: Non-static methods can access both static and non-static members
4: Accessing static properties directly does not require this pointer---print(name)
5: Static methods do not need to instantiate classes---Person.show()
*/

object operator

? Conditional operator

main(List<String> args) {
    //No instantiation, p is empty, no error will be reported (nothing after p? This will report an error)
    Person p;
    p?._printInfo();

    //Instantiate, p1 is not empty, execute as usual
    Person p1 = new Person();
    p1?._printInfo();
}

class Person {
    String name = 'Tobu';
    int age = 25;
    _printInfo() {
        print('$name\n$age');
    }
}

as type conversion

var p;
p = '';
p = new Person();
(p as Person)._printInfo();//convert p to Person

is type judgment

Person p = new Person();
print(p is Object);//true

.. cascade operation

Person p = new Person('Tobu', 25);

p
    .._printInfo()
    ..name = 'Taco'
    ..age = 25
    .._printInfo();

// p._printInfo();
// p.name = 'Taco';
// p.age = 20;
// p._printInfo();

class inheritance

Inheritance of classes in Dart
1: The subclass uses the extends keyword to inherit the parent class
2: The subclass will inherit the properties and methods visible in the parent class, but will not inherit the constructor
3: The subclass can overwrite the method getter and setter of the superclass

extends inheritance

main(List<String> args) {
    Web w = new Web();
    //Subclasses access properties and methods visible to the parent class
    print(w.name);
    w._printInfo();
}
//Web subclass inherits parent class Person
class Web extends Person {}

class Person {
    String name = 'Tobu';
    int age = 25;
    _printInfo() {
        print('$name\n$age');
    }
}

super pass parameter to parent class constructor

main(List<String> args) {
    Web w = new Web('Tobu', 23);
    print(w.name);
    w._printInfo();
}

class Web extends Person {
    //Because the parent class constructor cannot be directly accessed by the child class, assign parameters to the parent class constructor through super
    Web(String name, int age) : super(name, age);
}

class Person {
    String name;
    int age;
    Person(this.name, this.age);
    _printInfo() {
        print('$name\n$age');
    }
}

Subclass properties and methods

main(List<String> args) {
    Web w = new Web('Tobu', 23, 'male');
    w._printInfo();
    w.run();
}

class Web extends Person {
    //Subclass properties
    String sex;

    //Because the parent class constructor cannot be directly accessed by the child class, assign parameters to the parent class constructor through super
    Web(String name, int age, String sex) : super(name, age) {
        this.sex = sex;
    }
   /*Pass arguments to the parent class named constructor
   Web(String name, int age, String sex) : super.now(name, age) {
        this.sex = sex;
    }
    */

    //subclass method
    run() {
        print('$name\n$age\n$sex');
    }
}

class Person {
    String name;
    int age;
    Person(this.name, this.age);
    _printInfo() {
        print('$name\n$age');
    }
}

@override overrides (overrides) parent class methods

main(List<String> args) {
    Web w = new Web('Tobu', 23);
    w._printInfo();//Prioritize the subclass's own methods (override the superclass's method)
}

class Web extends Person {
    Web(String name, int age) : super(name, age);

    //Override parent class method
    @override
    _printInfo() {
        print('$name');
    }
}

class Person {
    String name;
    int age;
    Person(this.name, this.age);
    _printInfo() {
        print('$name\n$age');
    }
}

abstract class

abstract abstract class

Abstract classes in Dart: Dart abstract classes are mainly used to define standards. Subclasses can inherit abstract classes or implement abstract class interfaces.

1. An abstract class is defined by the abstract keyword

2. An abstract method in Dart cannot be declared with abstract, and a method without a method body is called an abstract method such as: eat();

3. If the subclass inherits the abstract class, it must implement the abstract method in it

4. If an abstract class is implemented as an interface, all the properties and methods defined in the abstract class must be implemented.

5. An abstract class cannot be instantiated, only subclasses that inherit it can.

Polymorphism in Dart:

1. It is allowed to assign the pointer of the subclass type to the pointer of the superclass type, and the same function call will have different execution effects.

2. The instance of the subclass is assigned to the reference of the parent class

3. Polymorphism means that the parent class defines a method and does not implement it, but lets the subclasses that inherit it implement it. Each subclass has different performances.

Such as the following abstract class example is the performance of polymorphism.

//define an abstract class
abstract class Animal {
  //An abstract method is an abstract method if it does not implement the method body
  eat();
  run();

  //non-abstract method
  printInfo() {
    print('I am a normal method in an abstract class');
  }
}

//Subclass Dog inherits abstract parent class Animal
class Dog extends Animal {
  @override
  eat() {
    print('puppy eating bone');
  }

  @override
  run() {
    // TODO: implement run
    print('puppy running');
  }
}

//Subclass Cat inherits abstract parent class Animal
class Cat extends Animal {
  @override
  eat() {
    print('cat eating fish');
  }

  @override
  run() {
    // TODO: implement run
    print('cat is running');
  }
}

main() {
  //instantiate class
  Dog d = new Dog();
  d.eat();
  d.run();

  //instantiate class
  Cat c = new Cat();
  c.eat();
  c.run();
}

implements interface

1. Ordinary classes or abstract classes can be implemented as interfaces

2. Use the implements keyword to implement

3. If a common class is implemented, all the properties and methods in the common class and abstract need to be rewritten

4. Because abstract classes can define abstract methods, ordinary classes cannot, so abstract classes are generally used to define interfaces

 abstract class Db {
  String uri;
  add(String data);
  save();
  delete();
}

class Mysql implements Db {
  @override
  add(String data) {
    print('This is Mysql of add method' + data);
  }

  @override
  save() {}

  @override
  delete() {}

  Mysql(this.uri);

  @override
  String uri;
}

class Mssql implements Db {
  @override
  add(String data) {}

  @override
  save() {}

  @override
  delete() {}

  @override
  String uri;
}

class Mongodb implements Db {
  @override
  add(String data) {}

  @override
  save() {}

  @override
  delete() {}

  @override
  String uri;
}

main(List<String> args) {
  Mysql mysql = new Mysql('xxxxxx');
  mysql.uri = '127.0.0.1';
  mysql.add('added data');
}

The difference between extends and implements

1. If the methods in the abstract class are reused, and the subclasses are bound by abstract methods, we use extends to inherit the abstract class.

2. If we only use abstract classes as standards, we use Implements to implement abstract classes.

multiple interfaces

abstract class A {
    String name;
    printA();
}

abstract class B {
    printB();
}

class C implements A, B {
    @override
    String name;

    @override
    printA() {
        print('printA');
    }

    @override
    printB() {
        print('printB');
    }
}

main(List<String> args) {
    C c = new C();
    c.printA();
    c.printB();
}

mixins (similar to multiple inheritance, no constraints)

1. Classes as mixins can only inherit from object and cannot inherit from other classes

2. Classes as mixins cannot have constructors

3. A class can mixins multiple mixins classes

4. mixins are by no means inheritance or interfaces, but a new feature

class Person {
    String name;
    int age;
    Person(this.name, this.age);
    printInfo() {
        print('$name--------$age');
    }
}

abstract class A {
    printA();
}

abstract class B {
    printB();
}
//Can inherit + mixins, the inherited parent class can have a constructor, but the mixins cannot have a constructor
class C extends Person with A, B {
    C(String name, int age) : super(name, age);

    @override
    printA() {
        print('printA');
    }

    @override
    printB() {
        print('printB');
    }
}

main(List<String> args) {
    C c = new C('Tobu', 25);
    c.printInfo();
    c.printA();
    c.printB();
}

Generics

generic method
//No generics are added,
getData1(value) {
    return value;
}

//Added generics to solve the problem of inconsistent parameter and return value types
T getData<T>(T value) {
    return value;
}

main(List<String> args) {
    //no type checking
    getData('Hello');

    //Add type checking, only the specified type of data can be entered
    print(getData<String>('Hello'));
}


//Popular understanding: generics are to solve the reusability of class interface methods, as well as support for unspecific data types (type verification)
generic class
main(List<String> args) {
    //Type verification, only String can be added
    PrintClass p = new PrintClass<String>();
    p.add('Tobu');
    p.printInfo();

    //Type check, only int can be added
    PrintClass p1 = new PrintClass<int>();
    p1.add(12);
    p1.printInfo();
}

//define generic class
class PrintClass<T> {
    List list = new List<T>();
    void add(T value) {
        this.list.add(value);
    }

    void printInfo() {
        for (var i = 0; i < this.list.length; i++) {
            print(this.list[i]);
        }
    }
}

generic interface
//define a generic interface
abstract class Cache<T> {
    getByKey(String key);
    setByKey(String key, T value);
}

class FileCache<T> implements Cache<T> {
    @override
    getByKey(String key) {}

    @override
    setByKey(String key, T value) {
        print('FileCache--setByKey:key=${key},value=${value}');
    }
}

class MemoryCache<T> implements Cache<T> {
    @override
    getByKey(String key) {}

    @override
    setByKey(String key, T value) {
        print('MemoryCache--setByKey:key=${key},value=${value}');
    }
}

main(List<String> args) {
    //Type verification, value can only be passed in String
    FileCache f = new FileCache<String>();
    f.setByKey('index', 'file1');
}

Posted by McChicken on Fri, 03 Jun 2022 08:19:12 +0530