1print(success || failure); //或运算 输出 true 2print(success && failure); //且运算 输出 false
} </code></pre>
<h4>集合类型</h4> <p>dart中定义集合直接使用List list=[],如果没有指定泛型,默认类型为dynamic类型,集合中可以添加任何数据类型的数据,一旦指定了泛型,那么就只能添加约束的类型数据。除了初始化的时候添加元素另外还可以通过API的方式像集合中添加数据,add添加单一数据,addAll添加集合。还有另外一种方式是通过List.generate来生成集合,它的第一个参数表示集合的大小,第二个参数表示集合的元素。</p> <pre><code> void _listType() { List list = [1, 2, 3, "list"]; //泛型为dynamic //报 type 'List<dynamic>' is not a subtype of type 'List<int>' 异常 //因为指定了intList的泛型为int 但是list的泛型为dynamic,随意赋值失败 //List<int> intList = list; List<int> intList2 = [1, 2, 3, 4, 5]; //定义int集合 list.add("hello"); //添加单一元素 list.addAll(intList2); //添加集合 print(list); //输出 [1, 2, 3, "list","hello",1, 2, 3, 4, 5]1List<String> strList = List.generate(2, (index)=> "我是第$index个元素"); //通过generate定义一个String集合 2print(strList); //输出 [我是第0个元素, 我是第1个元素]
} </code></pre>
<p>有了集合那么我们就需要遍历它,dart中常用的遍历集合方式有:</p> <pre><code> for (int i = 0; i < list.length; i++) { print(list[i]); }1for (var data in list) { 2 print(data); 3} 4 5list.forEach((it) { 6 print(it); 7});
</code></pre>
<p>上面三种遍历方式输出结果都为:</p> <pre><code>1, 2, 3, "list","hello",1, 2, 3, 4, 5 </code></pre> <h4>Map类型</h4> <p>Map类型是将key和value相关联的对象,key和value可以是任意类型的数据,并且key是唯一的,如果key重复那么后添加的会覆盖之前添加的数据。定义map类型直接看代码:</p> <pre><code> void _mapList() { Map map = {"lisi": 20, "zhangsan": 24}; //直接通过 {key:value} 方式定义 Map map2 = {}; map2[11] = 20; map2["zhangsan"] = "24"; //上面两个效果是一样的且都没有指定泛型。Map<int, int> intMap = {1: 2, 3: 4}; //指定map的泛型
} </code></pre>
<p>下面我们看下Map的遍历:</p> <pre><code> map.forEach((key, value) { print( "key:$key,value:$value"); //输出 key:lisi,value:20 和 key:zhangsan,value:24 });1map.map((key, value) { 2 return MapEntry(value, key); //返回一个新的map对象,我们将key value值进行颠倒后返回 3}).forEach((key, value) { 4 print("key:$key,value:$value"); //输出 key:20,value:lisi 和 key:24,value:zhangsan 5}); 6 7for(var key in map.keys){ //遍历map的key元素 同理还可以遍历map.values 8 print(key); //输出 lisi 和 zhangsan 9}
</code></pre>
<h4>dynamic、var、Object的区别</h4> <p>dynamic:动态数据类型,是所有Dart对象的基础类型, 在大多数情况下,通常不直接使用它,通过它定义的变量会关闭类型检查,这意味着 dynamic x = 'hello world'; 调用x.foo()方法时静态类型检查不会报错,但是运行时会crash,因为x并没有foo()方法,所以建议大家在编程时不要直接使用dynamic。</p> <p>var:是一个关键字,意思是“我不关心这里的类型是什么。”,系统会自动推断类型runtimeType;而且一旦指定了类型,就不可以修改。</p> <p>Object:是Dart对象的基类,当你定义:Object obj=xxx 时这时候系统会认为obj是个对象,你可以调用obj的toString()和hashCode()方法,因为Object提供了这些方法,但是如果你尝试调用obj.foo()时,静态类型检查会进行报错。</p> <p>综上不难看出dynamic与Object的最大的区别是在静态类型检查上。</p> <h1>面向对象</h1> <h4>类的定义和构造</h4> <p>定义一个dart类,使用class关键字加上类名,构造方法和类名相同,默认所有的类都是继承Object的。其中可以定义一些方法和变量,如:</p> <pre><code>class Person { String name; int age;//标准构造方法 Person(this.name, this.age);
//重载父类的toString方法 也是多态的重要体现 @override String toString() { return "name=$name,age=$age"; } } </code></pre>
<p>一个类继承另一个类使用关键字extends,如果父类没有默认无参构造函数,那么子类需要使用super对父类进行初始化,子类的变量使用this.xxx来指定初始化,如:</p> <pre><code>class Worker extends Person {String workType; String workAddress; //通过this来初始化子类字段,将其他字段交由父类初始化 Worker(this.workType,this.workAddress,String name, int age) : super(name, age); } </code></pre>
<p>上面代码中的 :super(name,age) 被称作为初始化列表,除了调用父类构造器,还可以初始化实例变量,不同的初始化变量之间用逗号隔开。</p> <pre><code>class Worker extends Person {String workType; String workAddress; String companyName;
//通过this来初始化子类字段,将其他字段交由父类初始化,这里指定了companyName的初始化。 //如果要初始化变量,那么其不可以在构造方法中定义 Worker(this.workType, this.workAddress, String name, int age) : companyName = "world", super(name, age); } </code></pre>
<p>我们还可以通过命名构造函数的方式初始化实例类。使用就是 类名.xx() 即可,主要注意的是当有变量的类型是final的时候,命名构造方法就要求其在构造方法中指定初始化。</p> <pre><code>class Worker extends Person {......
//命名构造函数 Worker.begin(Worker work) : super(work.name, work.age) { print("命名构造函数"); }
//假如有变量final String workAddress,那么就需要在构造方法中指定: //Worker.begin(Worker work,this. workAddress) : super(work.name, work.age) { // print("命名构造函数"); //}
} </code></pre>
<p>工厂构造函数就是都只返回同一个实例类,可以理解为Java中的单例模式。</p> <pre><code>class Logger { static Logger _logger;factory Logger() { if (_logger == null) { _logger = Logger._initInstance(); } return _logger; }
//通过命名构造函数初始化 Logger._initInstance(); } </code></pre>
<p>还有一种构造方法是命名构造和工厂构造的结合体,通常在网络请求的时候将json映射为object的时候使用,它有一个好处就是不需要将类的final变量作为参数传递给构造方法。提供了一种灵活获取类对象的方式。定义格式:factory 类名.方法名。</p> <pre><code>class Worker extends Person {......
factory Worker.workHard(Worker work) { return Worker.begin(work, ""); } } </code></pre>
<p>dart默认都会隐式的定义setter方法,对非空的变量还会增加getter方法。但是加了私有后,外界就无法访问变量了,需要我们手动的添加set和get方法。</p> <pre><code>class Worker extends Person {......
double _salary;
set salary(double value) => _salary = value;
get salary => _salary;
......
} </code></pre>
<h4>抽象类和方法</h4> <p>使用 abstract 修饰符来定义一个抽象类,该类不能被实例化。抽象类在定义接口的时候非常有用,实际上抽象类中也包含一些实现。如果一个类继承了抽象类要么实现它的抽象方法,要么也将自己定义成抽象类。一个抽象类中不一定要有抽象方法,但是有抽象方法的类一定是抽象类。</p> <pre><code>//抽象类 abstract class Animal { //抽象方法 void eat(); }//实现抽象类 class Dog extends Animal { //实现eat方法 @override void eat() { print("啃骨头"); } } </code></pre>
<h4>mixins</h4> <p>mixins 是在多个类层次结构中重用代码的一种方式。要使用 mixins ,在 with 关键字后面跟一个或多个 mixin 的名字(用逗号分开),并且with要用在extends关键字之后。</p> <p>mixins的特征:实现 mixin ,就创建一个继承 Object 类的子类(不能继承其他类),不声明任何构造方法,不调用 super。</p> <pre><code>//声明mixins类 class Pig { void action() { print("吃完就睡"); } }//使用mixins类,可以复用它的action方法 class Cat extends Animal with Pig { @override void action() { print("抓老鼠"); }
@override void eat() { print("吃猫粮"); } } </code></pre>
<h1>方法定义</h1> <p>方法是由返回值类型+方法名+参数构成。其中返回值类型可缺省,也可为void或者具体的类型。正常情况下都是由方法名的,但有一种特殊就是匿名方法。参数分为参数类型和参数名,其中参数类型可缺省。参数又分为可选参数和默认参数,他们都使用 {} 来定义。</p> <pre><code>class FunClass { //city为可选参数,town为默认参数 String fromWhere(country, {String city, String town = "小红帽村"}) { if (city != null) { return "我来自 $country $city $town"; } else { return "我来自 $country $town"; } } } </code></pre> <p>我们来调用打印下看看:</p> <pre><code>FunClass funClass = FunClass(); print(funClass.fromWhere("格林国")); //输出 我来自 格林国 哈哈村 print(funClass.fromWhere("格林国", city: "童话镇"));//输出 我来自 格林国 童话镇 哈哈村 </code></pre> <p>匿名方法有时候也被称为 lambda 或者 closure 闭包,可以把匿名方法赋值给一个变量,直接调用变量名即可。</p> <pre><code>var printI = (i) => print(i); </code></pre> <p>使用:</p> <pre><code>FunClass funClass = FunClass(); funClass.printI(999); </code></pre> <h1>泛型</h1> <p>泛型主要是解决类、接口、方法的复用性、以及对不特定数据类型的支持。</p> <pre><code>class Cache<T> { static final Map<String, Object> _cached = Map();void setItem(String key, T value) { _cached[key] = value; }
///泛型方法 T getItem(String key) { return _cached[key]; } } </code></pre>
<p>这里我们定义了一个缓存类,存储的类型被定义为泛型,提高代码的复用度。</p> <p>有时候我们在实现类似通用接口的泛型中,期望的类型是某些特定类型时,这时可以使用类型约束。</p> <pre><code>class Member<T extends Person> { T _person;///泛型作用:约束参数类型 Member(this._person);
String fixedName() { return 'fixed:${_person.name}'; } } </code></pre>
<h1>总结</h1> <p>本文主要是讲解了在Flutter中常用到的dart的基础知识,当然还有其他很多的知识点没有涉及到。这里推荐几个dart学习网站给大家使用。</p> <p><a href="https://links.jianshu.com/go?to=https%3A%2F%2Fwww.dartlang.org" target="_blank">https://www.dartlang.org</a></p> <p><a href="https://links.jianshu.com/go?to=https%3A%2F%2Fdart.dev%2Fguides%2Flanguage%2Flanguage-tour" target="_blank">https://dart.dev/guides/language/language-tour</a></p> <p><a href="https://links.jianshu.com/go?to=http%3A%2F%2Fdart.goodev.org%2Fguides%2Flanguage%2Flanguage-tour" target="_blank">http://dart.goodev.org/guides/language/language-tour</a></p>