Flutter Dart语言(03)面向对象总结

0 说明

该系列教程主要是为有一定语言基础 C/C++的程序员,快速学习一门新语言所采用的方法,属于在C/C++基础上扩展新语言的模式。

1 面向对象基础知识

说明:这里主要是基于C++面向对象着门语言,分析与其不同的部分,属于扩展式的学习模式。Dart语言本身也是面向对象的程序语言,

编码习惯说明:类的首字母要大写,方法首字母小写。

1.1 类的属性信息获取

在dart语言中,属性的获取一般可以用$符号直接获取,这里以Person类为例,具体描述如下:

class Person {
  String name = 'wang';
  int age = 30;
  Person() {}

  void printInfo() {
    print("printInfo:");
    print("use \$ label");
    print("$name----$age");
    print("use this pointer");
    print("${this.name}----${this.age}");
  }
}

void main() {
  Person p = new Person();
  p.printInfo();

  print("Person's property:");
  print("name=${p.name},age=${p.age}");
}

命令执行后效果如下:

Connecting to VM Service at ws://127.0.0.1:63468/DKkz_f3A8aw=/ws
printInfo:
use $ label
wang----30
use this pointer
wang----30
Person's property:
name=wang,age=30

1.2 默认构造函数和命名构造函数

Dart中构造函数和C++中有所不同,并不是直接编写的构造函数有多个,而是一个默认构造函数和多个不同的命名构造函数,都可以用于对象的实例化,这里以Person类为例来解读默认构造函数和命名构造函数的差别,代码如下所示:

class Person {
  String name = 'wang';
  int age = 30;

  //1 默认构造函数,当实例化一个对象时,会自动调用到该函数
  //一般编码模式:
  // Person(String name, int age) {
  //   this.name = name;
  //   this.age = age;
  // }
  //Dart语言中的简写模式,功能同上 注释:
  Person(this.name, this.age);

  //2 命名构造函数系列
  Person.now() {
    print("命名构造函数now");
  }
  Person.init(String name) {
    this.name = name;
    print("命名构造函数init:$name");
  }
  void printInfo() {
    print("$name---$age");
  }
}

void main() {
  Person p1 = new Person("wang", 30);
  Person p2 = new Person.now();
  Person p3 = new Person.init("li");

  p1.printInfo();
  p2.printInfo();
  p3.printInfo();
}

命令执行后效果如下:

Connecting to VM Service at ws://127.0.0.1:63783/veW3pzv-NKs=/ws
命名构造函数now
命名构造函数init:li
wang---30
wang---30
li---30

1.3 私有(private)属性和公有(public)属性

这里的private变量一般使“ _ ”开头,而非“_”开头的变量一般都是public变量。代码如下所示:

class Person {
  //public属性
  String name = 'wang';

  //private属性
  //注意:必须在Person独立出的类文件中,才可以使private属性生效,否则无效
  int _age = 30;

  Person(this.name, this._age);
  void printInfo() {
    print("$name---$_age");
  }
}

void main() {
  Person p1 = new Person("wang", 30);
  p1._age = 30;
  p1.printInfo();
}

但要非常注意:直接在该文件中使用时private属性并不生效,即外界依然可以访问。只有在独立类文件Person中时才会生效。命令执行后效果如下:

Connecting to VM Service at ws://127.0.0.1:64385/Oid5LlpsVOg=/ws
wang---30

1.4 get和set 计算属性

get和set的使用,代码如下所示:

class Circle {
  double radius;
  Circle(this.radius);

  //getter实现
  // double s() {
  //   return radius * radius * 3.14;
  // }
  //{等价于上面的方法实现}

  //setter实现
  set setRadius(double radius) {
    this.radius = radius;
  }
}

void main() {
  Circle c = new Circle(5.0);
  c.setRadius = 7.0;//setter的使用
  print("r=${c.radius},s=${c.s}");//getter的使用
}

命令执行后效果如下:

Connecting to VM Service at ws://127.0.0.1:64936/um9Y1LlW7Zc=/ws
r=7.0,s=153.86

1.5 初始化操作

构建对象前的初始化变量操作,在构造函数运行前赋值,代码如下所示:

class Circle {
  double radius;
  //变量初始化操作。在构造函数运行前赋值
  Circle() : radius = 3.0 {
    print("r=${radius}");
  }

  get s {
    return this.radius * this.radius * 3.14;
  }
}

void main() {
  Circle c = new Circle();
  print("r=${c.radius},s=${c.s}");
}

命令执行后效果如下:

Connecting to VM Service at ws://127.0.0.1:65060/-cx0Vbd4POI=/ws
r=3.0
r=3.0,s=28.26

1.6 静态属性和静态方法

在Dart语言中一般使用static关键字来实现对变量和方法的描述。规则如下:

  • 静态方法中不能使用非静态方法和属性。
  • 非静态方法中可以使用静态方法和静态属性。

1.7 级联操作..

代码实现如下:

class Person {
  String name = 'wang';
  int age = 30;

  Person(this.name, this.age);
  void printInfo() {
    print("$name---$age");
  }
}

void main() {
  Person p1 = new Person("wang", 30);

  //级联操作赋值
  p1
    ..name = "wang-5"
    ..age = 40
    ..printInfo();
}

命令执行后效果如下:

Connecting to VM Service at ws://127.0.0.1:50341/2a365aWm2oY=/ws
wang-5---40

常量构造函数

2 面向对象(继承、封装、多态)

2.1 抽象类和抽象方法

这里的描述主要针对相比C++语言的抽象类中不同之处,做对比学习,如下:

  • 抽象类主要用于定义标准。使用abstract关键字,抽象类中的抽象方法则无需再使用abstract关键字来声明。
  • 抽象类中如果只声明方法但不实现则是抽象方法,即没有方法体的方法就是抽象方法了。如果实现了的方法就是普通方法,即有方法体的方法。

抽象类及对应方法 代码实现如下:

//抽象类
abstract class Animal {
  //抽象类中的抽象方法
  void eat();
  void run();

  //抽象类中的一般方法
  void printInfo() {
    print("class Animal info");
  }
}

2.2 implements接口

Dart中没有关键字来定义接口的关键字,普通类和抽象类都可以作为接口被实现,使用关键字implements关键字进行实现。如果实现的类是普通类,需要将普通类和抽象中的属性和方法全重写。抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现接口的方式,使用抽象类定义接口。这里要注意extends和implemnets的区别:在Dart语言中,继承抽象类 和实现抽象类是不同的,继承只会重写抽象类里的抽象方法,而实现会重写抽象类里的所有变量和方法。相关代码如下所示:

//复用上一段代码的Animal。。。

//继承:只需要重写抽象类中的抽象方法
class Cat extends Animal {
  @override
  void eat() {
    // TODO: implement eat
  }

  @override
  void run() {
    // TODO: implement run
  }
}
//实现需要重写抽象类中的所有属性和方法
class Dog implements Animal {
  @override
  late String name;

  @override
  void eat() {
    // TODO: implement eat
  }

  @override
  void printInfo() {
    // TODO: implement printInfo
  }

  @override
  void run() {
    // TODO: implement run
  }

}

说明:如果是implements实现多个抽象类,则需要重写多个抽象类里的所有变量和方法。

2.3 mixins功能

主要用于实现类似多继承的功能。mixins的使用条件随着Dart的版本不断更新而有所改,mixins 3.X版本中约束条件如下:

  • 作为mixins的类只能继承自Object,不能继承其他类
  • 作为mixins的类不能有构造函数
  • 一个类可以mixins多个mixins类
  • mixins不是继承,也不是接口,而是一种全新的特性

代码实现如下所示:

mixin A {
  //作为minxins类,只能继承自Object
  printA() {
    print("This is A");
  }

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

mixin B {
  //作为minxins类,只能继承自Object
  printB() {
    print("This is B");
  }

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

//C混合了A类和B类,类似继承,C的实例化类可以使用A类以及B类中的方法
class C with A, B {}

main() {
  C c = new C();
  c.printA();
  c.printB();
  c.run();
}

命令执行后效果如下:

Connecting to VM Service at ws://127.0.0.1:55350/kWXd6C3DRl4=/ws
This is A
This is B
run B

注意:如果有相同方法,则执行时主要依赖with的顺序。

同时这里也可以同时extends其他类基础上再使用mixins机制。关键代码如下所示:

class C extends  X with A, B {}

2.4 late关键字

表示延迟初始化,不在对象初始化时初始化,而是在对象初始化之后。参考2.2 implements接口中demo。

2.5 identical函数

主要用于检查两个引用是否指向同一个对象。关于identicial的判定,参考如下代码:

void main() {
  var o1 = new Object();
  var o2 = new Object();
  var isIdentical = identical(o1, o2); // false, diff objects.
  isIdentical = identical(o1, o1); // true, same object
  isIdentical =
      identical(const Object(), const Object()); // true, const canonicalizes
  isIdentical = identical([10], [10]); // false
  isIdentical = identical(const [10], const [10]); // true
  isIdentical = identical(const [1], const [2]); // false
}

2.6 常量构造函数

在Dart语言中,const一方面是内存开销减少,另一方面源自从常量组件是不应该改变的需求。常量构造函数需要满足以下约束:

  • 常量构造函数需要以const关键字修饰;
  • const构造函数必须用于成员变量都是final的类;
  • 如果实例化不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例对象;
  • 实例化常量的构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象;

这里给出一个demo,代码如下所示:

class Rect {
  final int width;
  final int height;
  const Rect(
      {required this.width, required this.height}
  ); 
}

3 泛型

和C++基本一致,主要解决代码中数据类型的复用问题。一般都是泛型方法和泛型类中使用。

你可能感兴趣的:(Flutter,APP,开发语言,flutter)