最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 浅谈 Dart 类与类的基本方法

    正文概述 掘金(ssssyoki)   2021-08-27   647

    一、Dart 语言

    Dart 是一门面向对象的语言。

    Dart 语言中所有的变量引用都是一个对象,并且所有的对象都对应一个类的实例。无论是数字、函数和null ,都是一个对象,所有对象继承自Object类。

    在 Dart 2.13 及以上版本,如果开启空安全(sound null safety)那么除了null之外的所有类都继承自 Object

    Object

    Object 具有下列特性:

    • 两个属性:hashCoderuntimeType
    • 两个方法:noSuchMethodtoString
    • 操作符:Operator

    hashCode

    hashCode 是 read-only 属性的 int 类型数据,因为 Dart 所有的变量引用均继承于Object,所以每个变量引用都有自己的hashCodehashCode的设计目的是为了提高 Dart VM 引擎在解析数据结构时的效率,并且参与判断对象的逻辑运算,与操作符 operator 相辅相成。考察如下代码:

    void main() {
        P p1 = P("yo","no");
        P p2 = P("yo","no");
      
        print(p1 == p2);
        print(p1.hashCode);
        print(p2.hashCode);
        
        Map<P, String> myMap = {};
        myMap[p1] = "first Item";
    
        print(myMap.containsKey(p2));
    }
    
    class P {
        var naam;
        var kaam;
        P(this.naam, this.kaam);
        
        @override
        int get hashCode {
            int result = 11 * naam.hashCode;
            result = 13 * (result + kaam.hashCode);
            return result;
        } 
        
        @override
        bool operator == (dynamic otherObj) {
            return (otherObj is P) && (otherObj.naam == naam) && (otherObj.kaam == kaam);
        }
    }
    

    代码重写了P对象的比较相等的逻辑,从而令p1p2的比较结果返回为true。但同时需要重写hashCode的逻辑,否则返回值仍旧为false

    Dart 建议hashCodeOperator如有必要重写其中之一,那么另一个也需要重写,从而令哈希映射正常工作,否则Operator重写无效。

    runtimeType

    runtimeType是 read-only 属性,表达数据结构在运行时的类型。runtimeType涉及 Dart VM 运行机制,此处留坑以后再来填。

    noSuchMethod

    当调用对象上不存在的方法时,就会触发noSuchMethod,考察如下代码:

    void main() {
        P p = P();
        print(p.add(888));
    }
    
    class P {
        @override
        noSuchMethod(Invocation invocation) => 
            'Got the ${invocation.memberName} with arguments ${invocation.positionalArguments}';
    }
    

    在 DartPad 编辑器运行上述代码,发现并未触发noSuchMethod方法, 而是直接抛出了编译错误。实际noSuchMethod触发需要有两个条件:

    • 调用方必须是dynamic类型;
    • 调用方具有被调用方法的定义但未实现,同时noSuchMethod也被重写;

    所以只有如下两种情况,才会触发noSuchMethod

    void main() {
        dynamic p = P();
        Q q = Q(); // 该情况下,q 可以是 Q 类型,也可以是 dynamic
        print(p.add(123));
        print(q.add(123));
    }
    
    class P {
        @override
        noSuchMethod(Invocation invocation) => 'Got the ${invocation.memberName} with arguments ${invocation.positionalArguments}';
        }
        
    class Q {
        miss(int data);
        @override
        noSuchMethod(Invocation invocation) => 'Got the ${invocation.memberName} with arguments ${invocation.positionalArguments}';
    }
    

    toString

    toString方法使用字符串来表达对象的信息,也可以在将数字转换为字符串的场景下使用。开发者也可以重写 toString方法,以加入自定义内容。

    void main() {
        P p = P();
        p.toString();
    }
    
    class P {
        @override
        toString() {
            return 'this is custom text'
        } 
    }
    

    二、Dart 类与基本方法

    1.类的定义和构造函数

    class P {
        String name;
        int age;
        
        P(String dataName, int dataAge) {
            name = dataName;
            age = dataAge;
        } 
        
        bool isOld() {
            return age > 30 ? true : false;
        } 
    }
    
    void main() {
        var p = new P('tom', 12);
        print(p.name);
    }
    

    上述代码中,声明了P类,P 中含有两个属性:nameage。同时也声明了构造函数,通过向构造函数传入参数从而创建实例p

    创建实例仍然使用传统的new方法,但在 Dart 2 以上版本,new关键字可以省略,同时构造函数也可以用语法糖简化,代码写法如下:

    class P {
        String name;
        int age;
        
        P(this.name, this.age);
        
        bool isOld() {
            return age > 30 ? true : false;
        }
    }
    
    void main() {
        var p = P('tom', 12);
        print(p.name); // tom
    }
    

    命名构造函数

    除默认的构造函数外,Dart 提供命名构造函数方法。代码如下:

    class P {
        String name;
        int age;
        
        P(this.name, this.age);
        
        P.init(String dataName, int dataAge) {
            name = dataName;
            age = dataAge;
        } 
        
        bool isOld() {
            return age > 30 ? true : false;
        }
    }
    
    void main() {
        var p = P.init('tom', 12);
        print(p.name); // tom
    }
    

    命名构造函数的功能看起来与默认构造函数的功能类似,那设计该机制的目的是什么呢?原因是 Dart 不支持构造函数的重载,无法使用不同的参数来执行构造方法,所以提供命名构造函数的机制来实现多方式创建实例。

    工厂构造函数

    除了上述两种构造函数外,Dart 还提供第三种构造函数:工厂构造函数。它的使用场景是:如果调用构造函数时,如果实例已存在,不会重新创建实例,而是使用已存在的实例,保证环境内只有一个实例存在,也就是单例模式。考察如下代码:

    class P {
        String name;
        static Map<String, dynamic> _cache = {};
        
        factory P(String name) {
            if (_cache.containsKey(name)) {
                return _cache[name];
            } else {
                final p = P._internal(name);
                _cache[name] = p;
                return p;
            }
        }
        
        P._internal(this.name);
    }
    
    void main() {
        final p = P('tom');
        print(p.name);
    }
    

    工厂构造函数不允许访问this,所以_cache的形态必须是static。每次创建实例时,如果实例已经在_cache中存在,那么返回已存在的实例。换句话说,工厂构造函数并没有自动创建实例,而是把决定权交给开发者。

    2.类的属性和方法

    静态变量和静态方法

    和大多数语言一样,Dart 提供静态变量和静态方法:

    class P {
        static age;
        static bool isOld() {
            return age > 30 ? true : false;
        }
    }
    

    静态方法无法使用this,也不能访问非静态成员,类的实例也无法调用静态方法,并且静态变量只有在被使用的时候才会初始化。

    私有属性和私有方法

    Dart 不提供类似publicprotected等关键字,在变量前添加下划线即可声明私有:

    class P {
        int _age;
        P(this._age);
        
        bool _isOld() {
            return this._age > 30 ? true : false; 
        } 
        
        bool isOld() { 
            return _isOld(); 
        }
    }
    
    void main() {
        final p = P(20);
        print(p._age);     // error
        print(p._isOld()); // error 
        print(p.isOld());  // false 
    }
    

    实例无法直接调用私有方法,但是可以通过调用公有方法的形式间接调用私有方法。

    3.类的继承

    构造函数

    Dart 通过extends关键字实现继承,子类继承父类中公有的属性和方法,不会继承构造函数,所以子类的构造函数需通过super关键字来调用或改造父类的构造函数:

    class P {
        num name;
        num age;
        
        P(this.name, this.age);
        P.xxx(this.name, this.age); }
    
    // class Q extends P {
    //     Q(num name, num age): super(name, age); 
    // } 
    
    // class Q extends P { 
    //     num sex; 
    //     Q(num sex, num name, num age): super.xxx(name, age) {
    //         this.sex = sex;
    //     } 
    // } 
    
    class Q extends P { 
        num sex; 
        Q(num sex, num name, num age): super(name, age) { 
            this.sex = sex;
        }
    }
    
    void main() {
        final q = Q(12, 13, 14);
        print(q.sex); // 12 
    }
    

    上述代码演示了子类中三种构造函数的表现:

    • 直接复用父类构造函数
    • 复用和改造父类默认构造函数
    • 复用和改造父类命名构造函数

    子类调用父类方法

    如果子类需要调用父类方法,同样使用super关键字,此时方法内部的this指向子类:

    class P {
        num name;
        num age; 
        
        P(this.name, this.age); 
        
        bool childCheck() { 
            return age > 20 ? true : false; 
        } 
    } 
    
    class Q extends P { 
        Q(num name, num age): super(name, age); 
        
        bool check() { 
            return super.check(); 
        } 
    }
    
    void main() { 
        final a = Q(12, 13); 
        print(a.childCheck()); // false
    }
    

    子类重写父类方法

    class P { 
        num name; 
        num age; 
        
        P(this.name, this.age); 
        
        bool check() { 
            return age > 20 ? true : false; 
        } 
    } 
    
    class Q extends P { 
        Q(num name, num age): super(name, age); 
        
        @override
        bool childCheck() { 
            return age == 13 ? true : false; 
        } 
    }
    
    void main() { 
        final a = Q(12, 13); 
        print(a.childCheck()); // true 
    }
    

    子类在重写父类方法时,只要方法名称与父类相同,便可实现逻辑重写,@override为可选项,对于复杂逻辑的类功能建议添加。


    下载网 » 浅谈 Dart 类与类的基本方法

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元