zoukankan      html  css  js  c++  java
  • Dart函数、类和运算符-处理信息

    编程语言虽然千差万别,但归根结底,它们的设计思想无非就是回答两个问题:

    1、如何表示信息;

    2、如何处理信息;

    函数

    函数是一段用来独立地完成某个功能的代码。函数是对象类型,它的类型叫做Function。这意味着函数也可以被定义为变量,甚至可以被定义为参数传递给另一个函数。
    bool isZero(int number) => number == 0;
    void printInfo(int number, Function check) => print("$number is Zero: ${check(number)}");
    
    如果函数体只有一行表达式,就可以像JavaScript语言那样用箭头函数来简化这个函数

    一个函数中可能需要传递多个参数。如何让这类函数的参数声明变得更加优雅、可维护,同时降低调用者的使用成本?

    C++与Java的做法是,提供函数的重载,即提供同名但参数不同的函数。但Dart认为重载会导致混乱,因此从设计之初就不支持重载,而是提供了可选命名参数和可选参数。
    bool isZero(int number) => number == 0;
    void printInfo(int number, Function check) => print("$number is Zero: ${check(number)}");
    
    // 要达到可选命名参数的用法,那就在定义函数的时候给参数加上{}
    void enableFlagsA({bool bold, bool hidden}) => print("$bold, $hidden");
    
    // 定义可选命名参数时增加默认值
    void enableFlagesB({bool bold = true, bool hidden = false}) => print("$bold, $hidden");
    
    // 可忽略的参数在函数定义时用[]符号指定
    void enableFlagesC(bool bold, [bool hidden]) => print("$bold, $hidden");
    
    // 定义可忽略参数时增加默认值
    void enableFlagesD(bool bold, [bool hidden = false]) => print("$bold, $hidden");
    

    类是特定类型的数据和方法的集合,也是创建对象的模版。

    类的定义及初始化

    Dart是面向对象的语言,每个对象都是一个类的实例,都继承自顶层类型Object。 Dart中并没有public、protected、private这些关键字,只要在声明变量与方法时,在前面加上_即可作为private方法使用,如果不加_,则默认为public。不过_的限制范围并不是类访问级别的,而是库访问级别。

    class Point {
      
      num x, y;
      static num factor = 0;
      // 语法糖,等同于在函数体内:this.x = x; this.y = y;
      Point(this.x, this.y);
      void printInfo() => print('($x,$y)');
      static void printZValue() => print('$factor');
    }
    
    有时候类的实例化需要根据参数提供多种初始化方法。除了可选命名参数和可选参数之外,Dart还提供了命名构造函数的方式,使得类的实例化过程语义更清晰。

    此外,与C++类似,Dart支持初始化列表。在构造函数的函数体真正执行之前,还有机会给实例变量赋值,甚至重定向至另一个构造函数。

    class Point {
      num x, y, z;
      Point(this.x, this.y) : z = 0; // 初始化变量z
      Point.bottom(num x) : this(x, 0); // 重定向构造函数
      void printInfo() => print('($x, $y, $z)');
    }
    
     var p = Point.bottom(100);
     p.printInfo(); // 输出(100,0,0)
     
    

    复用

    在面向对象的编程语言中,将其他类的变量与方法纳入本类中进行复用的方式一般有两种:继承父类和接口实现。

    在Dart中,可以对同一个父类进行继承或接口实现:
    • 继承父类意味着,子类由父类派生,会自动获取父类的成员变量和方法实现,子类可以根据需要覆写构造函数及父类方法;
    • 接口实现则意味着,子类获取到的仅仅是接口的成员变量符号和方法符号,需要重新实现成员变量,以及方法的声明和初始化,否则编译器会报错。
    class Point {
      num x = 0, y = 0;
      void printInfo() => print('($x, $y)');
    }
    
    // Vector 继承自 Point
    class Vector extends Point {
    
      num z = 0;
      @override
      void printInfo() => print('($x,$y,$z)'); // 覆写了printInfo实现
    }
    
    // Coordinate 是对 Point 的接口实现
    class Coordinate implements Point {
    
      num x = 0, y = 0; // 成员变量需要重新声明
      void printInfo() => print('($x, $y)'); // 成员函数需要重新声明实现
    }
    
    var xxx = Vector();
      xxx
        ..x = 1
        ..y = 2
        ..z = 3; // 级联运算符,等同于 xxx.x = 1; xxx.y = 2; xxx.z = 3;
      xxx.printInfo(); // 输出(1,2,3var yyy = Coordinate();
      yyy
        ..x = 1
        ..y = 2; // 级联运算符,等同于 yyy.x = 1; yyy.y = 2;
      yyy.printInfo(); // 输出 (1,2print(yyy is Point); // true
      print(yyy is Coordinate); // true
    
    除了继承和接口实现之外,Dart还提供了另一种机制来实现类的复用,即“混入"(Mixin),混入鼓励代码重用,可以被视为具有实现方法的接口。不仅可以解决Dart缺少对多重继承的支持问题,还能够避免由于多重继承可能导致的歧义(菱形问题)。

    要使用混入,只需要with关键字即可。

    class Coordinate with Point {
    
    }
    
      var yyy = Coordinate();
      yyy
        ..x = 1
        ..y = 2; // 级联运算符,等同于 yyy.x = 1; yyy.y = 2;
      yyy.printInfo(); // 输出 (1,2)
      print(yyy is Point); // true
      print(yyy is Coordinate); // true
    
    可以看到,通过混入,一个类里可以以非继承的方式使用其他类中的变量与方法。

    运算符

    Dart和绝大多数编程语言的运算符一样,除外,Dart多了几个额外的运算符,用于简化处理变量实例缺失(即null)的情况。
    • ?. 运算符:假如Point类有printInfo()方法,p是Point的一个可能为null的实例。那么,p调用成员方法的安全代码,可以简化为p?.printInfo(),表示p为nul的时候跳过,避免抛出异常。
    • ??= 运算符:如果a为null,则给a赋值value,否则跳过。这种用默认值兜底的赋值语句在Dart中我们可以用a ??= value表示。
    • ?? 运算符:如果a不为null,返回a的值,否则返回b。在Java或者C++中,我们需要通过三元表达式(a != null)? a:b 来实现这种情况。而在Dart中,这类代码可以简化为 a ?? b。
    在Dart中,一切都是对象,就连运算符也是对象成员函数的一部分。
    对于系统的运算符,一般情况下只支持基本数据类型和标准库中提供的类型。而对于用户自定义的类。如果想要支持基本操作,比如比较大小、相加相减等,则需要用户自己来定义关于这个运算符的具体实现。

    Dart提供了类似C++的运算符覆写机制,使得我们不仅可以覆写方法,还可以覆写或者自定义运算符。

    class Vector {
      num x, y;
      Vector(this.x, this.y);
      // 自定义相加运算符,实现向量相加
      Vector operator + (Vector v) => Vector(x + v.x, y + v.y);
    
      // 覆写相等运算符,判断向量相等
      bool operator == (dynamic v) => x == v.x && y == v.y;
    }
    
      final x = Vector(3,3);
      final y = Vector(2,2);
      final z = Vector(1,1);
      print(x==(y+z)); // 输出 true
    
    operator 是 Dart 的关键字,与运算符一起使用,表示一个类成员运算符函数。在理解时,我们应该把 operator 和运算符作为整体,看作是一个成员函数名。
  • 相关阅读:
    PHP里json_encode()与json_decod()区别
    数组进行排序
    tp5利用自带上传类实现单个文件与多文件上传
    mkdir() Permission denied 报错问题
    如何快速熟悉新项目的代码?
    Tp5自定义路径写入日志
    spring解决循环依赖
    spring注解的使用
    ssm的整合
    编程知识总结
  • 原文地址:https://www.cnblogs.com/shsuper/p/11574088.html
Copyright © 2011-2022 走看看