美文网首页dart语法基础
Dart语法基础之对象,接口,类以及多继承

Dart语法基础之对象,接口,类以及多继承

作者: 奔跑的杰尼龟zxl | 来源:发表于2019-04-06 16:25 被阅读0次

    Dart语言特性

    Dart是纯面向对象,基于类,使用可选类型支持混入式继承及Actor模式的并发编程语言。

    万物皆对象

    Dart是一门纯面向对象的编程语言,这意味着Dart程序在运行时所处理的值都是对象,甚至包括数字,布尔等数据。例如number int double 都是对象类型,举例而言int不主动赋值,默认是null,这就是强大的万物皆对象。

    面向接口编程
    • Dart的类型基于接口,而不是类。任意类都隐含了一个接口,能够被其他类实现
    • Dart没有final方法,允许重写几乎所有的方法
    • Dart把对象进行了抽象封装,确保所有外部操作都能通过存取方式来改变对象的状态
    • Dart 的构造函数允许对对象进行缓存,或者从子类型创建实例,因此使用构造函数并不意味着绑定一个具体的实现了
    类型可选 类C
    • 类型在语法层面上是可选的
    • 类型对运行时语义没影响
    • 类C 选择保守 渐进的修改

    在开始内容之前我们先看一个这样的例子吧

    import 'dart:math';
    class Point{
      var x, y;
      Point(this.x,this.y);
      operator +(p)  => new Point(x + p.x, y + p.y);
    
      /// get 的调用语法与变量的访问是没有区别的
      /// 实际上dart中所有变量的访问都是调用的get,每个实例变量始终有一个与之关联的get方法
      get doubleX => x * 2;
    
      /// 设置值
      set newY(newY){
        this.y = newY;
      }
    
      /// static 修饰符表明此方法不针对某个特定实例,无法访问实例变量x,y
      /// static 修饰的类方法是不会被继承的
      static distance(Point p1,Point p2){
        var dx = p1.x - p2.x;
        var dy = p1.y - p2.y;
        return sqrt(dx * dx + dy * dy);
    
      }
    }
    
    import 'Point.dart';
    void main(){
      Point pointA = new Point(10, 10);
      Point pointB = new Point(10, 10);
      Point pointPlus = pointA + pointB;
      var x = pointPlus.x;
      var y = pointPlus.y;
      print('合并后 X = $x,Y = $y');
      var doubleX = pointPlus.doubleX;
      print('double X = $doubleX');
      pointPlus.newY = 100;
      print(pointPlus.y);
      //  合并后 X = 20,Y = 20
      //  double X = 40
      //  100
    }
    

    1.Dart中变量

    1.1实例变量

    当一个类声明一个实例变量时,它会确保每个实例都有自己的唯一的变量复制。对象的实例变量需要占用内存,这块内存是在对象创建时分配的。Dart会将每个新分配的变量(实例变量,局部变量,类变量和顶层变量)初始化为null。在Dart中,与其他对象一样,null也是一个对象。声明实例或者静态变量会自动引入一个get。如果变量是可变的,则一个set方法也会被自动定义。
    如上,对于程序中的变量x,y,我们给予直接赋值也是可以的,
    如 point.x = numberA 。dart帮我们定义好了get以及set方法,不必像java还要去针对每个变量设置get以及set方法。

    1.2类变量(static变量)

    一个类中只有一份类变量的副本,无论他有多少个实例,即使类没有实例,类变量也存在。类变量是延迟初始化(懒加载)的,在getter(get)第一次被调用时类变量才执行初始化,该时机在第一次尝试读取它时。默认初始化为null。

    1.3 final变量

    表明在初始化后就不能进行修改了。该字段有setter方法,但是没有getter方法。必须保证在任何实例方法运行前就进行初始化。
    初始化的时机:

    1. 声明变量时就初始化
    2. 构造函数初始化
    3. 通过初始化列表
    4. 应当明确不能在构造函数的 { }内设置final变量的值,因为该类型变量无setter,普通变量可以
    class FinalClass {
      // 1.声明赋值
      final String name = 'apple';
      final int age;
      final bool isMan;
      // 2.构造函数初始化
      FinalClass(this.age,this.isMan);
    }
    
     /// 注意构造函数后的 : 
      final String name;
      final String doubleName;
      final int age = 18;
      HappyCat(this.name):doubleName = name+name;
    
    1.4 相同与相等
    class Girl{
      final String name;
      final int age;
    
      Girl(this.name, this.age);
    
      @override
      bool operator ==(other) {
        /// dart中类型判断 is / is!
        if(other is! Girl){
          return false;
        }
        /// 强制类型转换
        Girl otherGirl = other as Girl;
        return otherGirl.name == name && otherGirl.age == age;
      }
    
      // 如果2个对象相等,那么哈希码也应该相等
      @override
      int get hashCode => name.hashCode+age.hashCode;
    }
    
      Girl girlA = new Girl('小徐', 18);
      Girl girlB = new Girl('小徐', 18);
      bool isEquals =  girlA == girlB;
      print(isEquals.toString());
      // true
    

    2. 抽象类与接口

    2.1 抽象方法与抽象类

    /// 抽象类
    abstract class Animal{
    
      final String name;
    
      Animal(this.name){
        print('构造函数 Animal');
      }
    
      /// 抽象类中可包括实例方法
      void eat(){
        print('$name 正在吃东西');
    
      }
    
      /// 抽象方法
      void hunt();
    }
    
    import 'Animal.dart';
    class Tiger extends Animal{
    
      Tiger(String name) : super(name){
        print('构造函数 Tiger');
      }
    
      @override
      void hunt() {
        print('我用四肢体捕猎物');
      }
    }
    
    import 'Tiger.dart';
    
    void main(){
      Tiger tiger = new Tiger('老虎A');
      tiger.eat();
      tiger.hunt();
    }
    
    //构造函数 Animal
    //构造函数 Tiger
    //老虎A 正在吃东西
    //我用四肢体捕猎物
    

    class A extends B with C 可实现类多继承

    2.2 接口

    接口继承使用关键字implments,但定义接口仍然使用abstract关键字

    abstract class HuntAction{
     void hunt();
    }
    
    abstract class JoyAction{
     void joy();
    }
    
    import 'HuntAction.dart';
    import 'JoyAction.dart';
    class HappyCat implements HuntAction,JoyAction{
      final String name;
      HappyCat(this.name);
    
      @override
      void hunt() {
        print('$name 是通过爪子捕猎的');
      }
    
      @override
      void joy() {
        print('$name 喜欢和老鼠玩');
      }
    }
    
      HappyCat happyCat = new HappyCat('小花');
      happyCat.hunt();
      happyCat.joy();
      ///小花 是通过爪子捕猎的
      ///小花 喜欢和老鼠玩
    

    3.0 构造函数

    3.1 重新向构造函数

    重定向构造函数的目的是执行重定向到另外一个构造函数。在重定向构造函数中,参数列表跟在一个冒号后面,并以this.constructor(x,y,z) 指定重定向到哪个函数上。

      HappyCat(this.name):doubleName = name+name;
      
      // 重定向构造函数不能包含初始化内容
      HappyCat.NextParams(String name):this.Params(name,'参数');
    
      HappyCat.OneParams(String name):this(name);
    
      HappyCat happyCat2 =  HappyCat.NextParams('小白');
      print(happyCat2.name+" "+happyCat2.params);
      // 小白 参数
      HappyCat happyCat3 =  HappyCat.OneParams('王子');
      print(happyCat3.name);
      // 王子
    
    3.2 工厂构造函数

    通常而言,构造函数都会重新分配一份新的实例。而工厂构造函数可以达到类似于缓存的功能。
    组织结构与特点:通常由factory前缀开头,它们可能没有初始化列表或初始化形式参数;它们必须又一个返回一个对象的函数体。工厂构造函数可以从缓存中返回对象,或选择分配一个新的实例。
    工厂构造函数是一种构造函数,与普通构造函数不同,工厂函数不会自动生成实例,而是通过代码来决定返回的实例对象.

    工厂构造函数实现单例

    class FactoryObject{
      String name;
      static FactoryObject cache;
    
      // 私有化构造函数
      // 类名.方法 实现的是匿名的构造方法
      FactoryObject._create(this.name);
    
      factory FactoryObject.getInstance(String name){
        if(cache == null){
          cache = new FactoryObject._create(name);
        }
        return cache;
      }
    }
    
      FactoryObject factoryOne = FactoryObject.getInstance('小王');
      print(factoryOne.name); // 小王
      FactoryObject factoryTwo = FactoryObject.getInstance('小白');
      print(factoryTwo.name); // 小王
      print(factoryOne == factoryTwo); // true
    

    4. 其他

    4.1 常量对象与字段

    q: 何时能够创建常量对象?
    先看一个错误的例子

    class Point{
      int x , y;
      Point(this.x, this.y);
    }
    
    
      // **报错**  The constructor being called isn't a const constructor
      Point point = const Point(10, 11);
    

    正确的例子

    class Point{
      final int x , y;
      // dart语法糖,在构造方法执行前进行赋值,所以可以给final进行初始化
      const Point(this.x, this.y);
    }
    // 正常
    Point point = const Point(10, 11);
    
    

    const 表达式也是调用构造函数,但该构造函数必须是常量构造函数,而且它的常量必须是常量。并且 常量构造函数不能有函数体,他可以有一个初始化列表,前提是只计算常量。

    相关文章

      网友评论

        本文标题:Dart语法基础之对象,接口,类以及多继承

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