Dart-语法二

作者: 葱花思鸡蛋 | 来源:发表于2020-09-21 18:24 被阅读0次

    面向对象特性

    1.类(class )

    Dart是一个面向对象编程语言,同时支持基于mixin的继承机制。每个对象都是一个类的实例,所有的类都继承于object。

    1)构造函数
    构造函数不能继承。父类的命名构造函数也不会被继承,如果子类也有父类一样命名构造函数,就必须在子类中自己实现该构造函数。

    • 默认构造函数:如果未显式定义构造函数,会默认一个参数为空的构造函数。默认构造函数会调用父类的无参构造函数。
    class  Person { //未定义父类的时候,默认继承自Object
      num x;
      num y;
      num z;
    }
    
    void main(List<String> args){
      var person = new Person();//调用默认的构造函数
      person.x = 10;   //使用点(.)引用实例变量或方法
      person.y = 11;
    }
    
    • 类名构造函数:就是一个与类同名的函数,关键字 this 是指当前实例,只有在命名冲突时有效,否则dart会忽略处理。
    
    class Point {
        int x;
        int y;
      //自己定义的类名构造函数
      Point(int x, int y) {
          this.x = x;
        this.y = y;
       }
       
       // 在构造函数里初始化成员属性是很常见的事情,因此Dart开发了新的语法糖来简化这种操作
       // 比如将Point的类名构造构造函数改写成
    
       // Point(this.x, this.y);
      // 注意x,y的赋值会在构造函数执行之前完成.
       
    }
    void main(){
        var point = new Point(1, 2);
    }
    
    
    • 命名构造函数:(类名.函数名)使用命名构造函数可以为类提供多个构造函数。
    class Point {
      num x, y;
    
      Point(this.x, this.y);
    
      // 命名构造函数
      Point.origin() {
        x = 0;
        y = 0;
      }
      // 简化
      // Point.origin(this.x,this.y);
      
    }
    
    
    • 重定向构造函数:有时构造函数的唯一目的是重定向到同一类中的另一个构造函数。重定向构造函数的主体为空,构造函数调用出现在冒号( :)之后 。
      大意就是在创建类时,我定义一个命名构造函数,但是这个构造函式的主体我不实现。直接通过:调用另外一个构造函数,实现对外界传入的参数的接收并赋值给内部的变量。
    class Point {
      num x, y;
      //类名构造函数
      Point(this.x, this.y);
      // 命名构造函数
     Point.order(this.x,this.y);
     Point.origin(num a,num b):this.order(a,b);  
     //重定向构造函数,origin构造函数将外界的传值,指向给了order构造函数。
    }
    
    
    • 工厂构造函数:在实现一个构造函数时使用factory关键字,该构造函数并不总是创建其类的新实例。例如,工厂构造函数可能会从缓存中返回实例,也可能会返回子类型的实例。工厂构造者对this没有访问权限。
    class Logger {
      final String name;
      bool mute = false;
    
     // _cache是私有变量
     //_在名称前,表示该变量为私有
      static final Map<String, Logger> _cache = <String, Logger>{};
    
      factory Logger(String name) {
        if (_cache.containsKey(name)) {
          return _cache[name];
         } else {
           final logger = Logger._internal(name);
           _cache[name] = logger;
           return logger;
        }
      }
    
      Logger._internal(this.name);
      void log(String msg) {
        if (!mute) print(msg);
       }
    }
    
    
    调用:
    var logger = Logger('UI');
    logger.log('Button clicked');
    
    
    • 常量构造函数:如果你的类创建的对象从不改变,你可以创建一些编译时的常量对象。因此,定义一个const构造函数,且保证所有的对象变量都是final。
    class ImmutablePoint {
      final num x;
      final num y;
      const ImmutablePoint(this.x, this.y);
      static final ImmutablePoint origin =
          const ImmutablePoint(0, 0);
    }
    
    

    注意:如果父类中没有默认的构造函数,你必须手动调用父类的构造函数,在子类的构造函数体之前通过(:) 指定调用父类构造函数,示例如下:

    // Person类中没有一个无参数,未命名的构造函数
    class Person {
      String firstName;
      // 命名构造函数
      Person.fromJson(Map data) {
        print('in Person');
      }
    }
    
    class Employee extends Person {
      // 你必须调用父类的super.fromJson(data).
      Employee.fromJson(Map data) : super.fromJson(data) {
        print('in Employee');
      }
    }
    
    main() {
      var emp = new Employee.fromJson({});
    }
    
    
    
    2.实例变量

    声明实例变量时,所有未初始化的实例变量的值为null。
    每个实例变量都会自动生成一个getter方法,Non-final(没有被final修饰)实例变量还会自定生成一个setter方法。

    class Point{
      num x;//声明实例变量x,初始化为空
      num y;//声明实例变量y,舒适化为空
      num z = 0;//声明实例变量z,初始化为0
      //如果在实例变量定义的时候初始化该变量(不是在构造函数或者其他方法中初始化),该值是在实例化对象的时
      //候初始化的,也就是在构造函数和初始化参数列表执行之前。
      
    }
    void main() {
      var point = new Point();
      point.x = 4;              //使用setter方法对x变量赋值
      print(point.x == 4);      //输出true 使用getter获取x变量的值
      print(point.y == null);   //输出true
    
    }
    
    

    静态(类)变量:使用static关键字来实现类级别的变量和方法,静态函数内部不能访问非静态成员,非静态函数能访问静态成员。

    class Queue {
      // 静态变量在使用之前不会初始化
      static const initialCapacity = 16;
      // ···
    }
    
    void main() {
      assert(Queue.initialCapacity == 16);
    }
    
    
    3.方法

    1)实例方法
    对象的实例函数可以访问this。
    import 'dart:math';

    class Point {
      num x;
      num y;
      Point(this.x, this.y);
    
      num distanceTo(Point other) {
        var dx = x - other.x;
        var dy = y - other.y;
        return sqrt(dx * dx + dy * dy);
      }
    }
    

    2)类方法
    使用static 修饰的方法,内部不能访问实例变量,没有访问this的权限。

    class Page{
      // 添加 static 关键字
      static int currentPage = 1;
      num size ;
      
      //类方法
      static void scorllDown(){
        currentPage = 1;
        // 访问实例变量报错
        // size = 10;
        print("ScrollDown...");
      }
     
      void scorllUp(){
        currentPage ++;
        print("ScrollUp...");
      }
    }
    
    void main(List<String> args) {
      var page = new Page();
      // 调用类方法
      Page.scorllDown();
    }
    
    
    

    3)Getters和Setters 方法
    Getters 和setters是用来设置和访问对象属性的特殊函数。每个实例变量都隐含的具有一个getter,如果变量不是final的则还有一个setter。使用get和set关键字定义getter和setter。

    class Rectangle {
      num left;
      num top;
      num width;
      num height;
    
      Rectangle(this.left, this.top, this.width, this.height);
    
      // 定义两个计算属性:右和下。
      num get right             => left + width;
          set right(num value)  => left = value - width;
      num get bottom            => top + height;
          set bottom(num value) => top = value - height;
    }
    
    main() {
      var rect = new Rectangle(3, 4, 20, 15);
      assert(rect.left == 3);
      rect.right = 12;
      assert(rect.left == -8);
    }
    
    

    4)抽象函数

    抽象函数是只定义函数接口但是没有实现的函数,由子类来实现该函数。如果用分号来替代函数体则这个函数就是抽象函数。

    abstract class Doer {
      // ...定义实例变量和方法...
    
      void doSomething(); // 定义一个抽象方法.
    }
    
    class EffectiveDoer extends Doer {
      void doSomething() {
        // ...提供实现,因此此处的方法不是抽象的...
      }
    }
    
    
    4.抽象类

    使用abstract修饰符定义一个抽象类,一个不能被实例化的类。抽象类通常用来定义接口,如果你想实例化抽象类,你必须实现抽象类,才能被实例化。

    // 这个类是抽象类,不能实例化
    abstract class AbstractContainer {
      // ...定义构造函数, 变量, 方法...
    
      void updateChildren(); // 抽象方法.
    }
    
    class SpecializedContainer extends AbstractContainer {
      // ...定义更多的构造方法, 方法...
    
      void updateChildren() {
        // ...实现 updateChildren()...
      }
    
    }
    
    
    
    5.隐式接口

    Dart中没有哪个关键字是来定义接口的, 默认情况下所有的类类都是都是隐式的接口,包括类的方法和属性。当将一个类当做接口使用时,那么实现这个接口的类,必须实现这个接口中所有的方法。

    // A person. 隐式接口包含greet().
    class Person {
      // 在接口中,但仅在此库中可见
      final _name;
    
      // 不在接口中,因为这是构造函数
      Person(this._name);
    
      // 在接口中
      String greet(who) => 'Hello, $who. I am $_name.';
    }
    
    // 实现Person 接口
    class Imposter implements Person {
      // 我们必须定义这个,但我们不使用它。
      final _name = "";
    
      String greet(who) => 'Hi $who. Do you know who I am?';
    }
    
    
    6.类的继承

    使用extends创建子类,super引用父类,子类可以重写实例方法、getter和setter,使用@override注释重写,使用@proxy注释来忽略警告

    class Person {
      
     void run{
         print('people run');
     }
     
    }
    
    class Kids{
        @override
        void run{
         print('Kids run');
     }
    }
    
    
    
    重写object的noSuchMethod()
    当用户调用你定义的类中不存在的属性与方法时,通过重写noSuchMethod(),可以做出一些响应。
    class A {
      @override
      void noSuchMethod(Invocation invocation) {
        print('You tried to use a non-existent member: ' +
            '${invocation.memberName}');
      }
    }
    
    
    
    7.访问控制

    默认类中的所有属性和方法是public的。在dart中,可以在属性和方法名前添加“_”使私有化。

    class Animal{
      String _name;   // 私有属性
      int age; 
      //默认构造函数的简写
      Animal(this._name,this.age);
    
      void printInfo(){   
        print("${this._name}----${this.age}");
      }
    
    // 供外部调用私有属性
      String getName(){ 
        return this._name;
      } 
      // 私有方法
      void _run(){
        print('这是一个私有方法');
      }
    
      execRun(){
        this._run();  //类里面方法的相互调用
      }
    }
    
    
    void main(){
     
     Animal a=new Animal('小狗', 3);
    
     print(a.getName());
    
      a.execRun();   //间接的调用私有方法
    
    }
    
    
    8.枚举类型

    枚举中的每个值都有一个index索引,它返回枚举声明中值的从零开始的位置。例如,第一个值具有索引0,第二个值具有索引1。

    enum Color { red, green, blue }
    
    assert(Color.red.index == 0);
    assert(Color.green.index == 1);
    assert(Color.blue.index == 2);
    
    

    可以在switch语句中使用枚举,如果不处理枚举的所有值,将会收到警告。

    9.泛型

    泛型就是定义的一个类型,类型暂不确定,给使用给一个占位符给代替,在使用的时候可以给确定其定义的类型。

    main() {
    // 如果自己希望List只包含字符串对象。则可以定义为List<String>代表("list of string")。
    
       List Tech = new List<String>();
       Tech.addAll(['Android','IOS','Flutter']);
       Tech.add(42);//运行时报错
    }
    
    

    相关文章

      网友评论

        本文标题:Dart-语法二

        本文链接:https://www.haomeiwen.com/subject/yxqbyktx.html