一、if、else、else if
int score = 43;
if(score >= 90){
if(score == 100){
print("完美");
}else{
print("优秀");
}
}else if(score > 60){
print("良好");
}else if(score == 60){
print("及格");
}else {
print("不及格");
}
执行结果:不及格
二、for、forin
var list = [1,2,3,4,5];
for(var index = 0;index < list.length; index++){
print(list[index]);
}
for(var item in list){
print(item);
}
执行结果:
1
2
3
4
5
1
2
3
4
5
三、while、do...while
int count = 0;
while(count < 5){
print(count++);
}
print("-----------$count-------------");
do{
print(count--);
}while(count > 0 && count < 5);
执行结果:
0
1
2
3
4
-----------5-------------
5
4
3
2
1
四、break、continue
var list1 = [1,2,3];
for(var item in list1){
if(item == 2){
break;
}
print(item);
}
执行结果:1
var list1 = [1,2,3];
for(var item in list1){
if(item == 2){
break;
}
print(item);
}
执行结果:
1
3
组合使用,循环嵌套
var list1 = [1,2,3];
var list2 = [4,5,6];
for(var item1 in list1){
if(item1 == 2){
break;
}
for(var item2 in list2){
if(item2 == 5){
break;
}
print(item2);
}
}
执行结果:4
注意:break只会跳出break所在最内层的循环
五、switch case
String language = "Java";
switch(language){
case "Dart":
print("Dart is my favorite");
break;
case "Java":
print("Java is my favorite");
break;
case "Python":
print("Python is my favorite");
break;
default:
print("None");
}
执行结果:Java is my favorite
特殊用法:语法——continue+标签
程序会直接跳转到标签标识的case位置继续执行
String language = "Java";
switch(language){
Tag:
case "Dart":
print("Dart is my favorite");
break;
case "Java":
print("Java is my favorite");
continue Tag;
case "Python":
print("Python is my favorite");
break;
default:
print("None");
}
执行结果:
Java is my favorite
Dart is my favorite
先执行case "Java",打印:“Java is my favorite”,之后continue Tag,程序跳转到名字为Tag的标签位置,Tag标识在case "Dart"之前,程序便跳转到case "Dart"继续执行,打印:“art is my favorite”
六、类与对象,声明、创建及基本特征
1、声明与创建
- 类与对象
- 使用关键字class声明类
- 使用关键字new创建对象,new可省了
var person = Person();
2、Dart 类的特性
- 属性默认生成getter和setter方法
- 使用final声明的属性只有getter方法
- 属性和方法通过.访问
- 方法不能被重载
class Person{
String name;
int age;
void work(){
print("Name is $name,Age is $age,He is working...");
}
}
var person = Person();
person.age = 12;
person.name = "tom";
print(person.age);
person.work();
3、计算属性
- 顾名思义,计算属性的值是通过计算而来,本身并不存储值
- 计算属性的赋值,其实是通过计算转换到其他的实例变量
class Rectangle{
num width,height;
num get area => width * height;
}
var rect = Rectangle();
rect.height = 20;
rect.width = 10;
print(rect.area);//200
七、构造方法及初始化列表
1、构造方法
- 如果没有自定义构造方法,则会有个默认构造方法
- 如果存在自定义构造方法,则默认构造方法无效
- 构造方法不能重载
class Boy{
String name;
int age;
Boy(String name, int age){
this.name = name;
this.age = age;
print("Name is $name,Age is $age");
}
void work(){
print("Name is $name,Age is $age,He is working...");
}
}
若存在final属性:
class Boy{
String name;
int age;
final String gender;
Boy(String name, int age,this.gender){
this.name = name;
this.age = age;
print("Name is $name,Age is $age");
}
void work(){
print("Name is $name,Age is $age,He is working...");
}
}
此时属性赋值在构造函数之前执行
构造方法语法糖:
Boy(this.name,this.age,this.gender);
同理属性赋值在构造函数之前执行
命名构造方法:
由于构造方法无法重载,要想给部分属性赋值时,可以采用赋值构造方法
class Boy{
String name;
int age;
inal String gender;
Boy(String name, int age,this.gender){
this.name = name;
this.age = age;
print("Name is $name,Age is $age");
}
Boy.withGender(this.gender);
void work(){
print("Name is $name,Age is $age,He is working...");
}
}
var boy = Boy.withGender("男");
boy.work();
常量构造方法:
- 如果类是不可变状态,可以把对象定义为编译时常量
- 使用const声明构造方法,并且所有变量都为final
- 使用const声明对象,可以省略
class Dog{
final String name;
final int age;
const Dog(this.name,this.age);
}
工厂构造方法:
- 工厂构造方法类似于设计模式中的工厂模式
- 在构造方法钱添加关键字factory实现一个工厂构造方法
- 在工厂构造方法中可返回对象
class Factory{
String message;
factory Factory(String message){
//message为dart时,实例化,否则返回空
if(message == "dart"){
return Factory.internal(message);
}else{
return null;
}
}
Factory.internal(this.message);
}
var factory = Factory("Java");
print(factory == null);//true
2、初始化列表
用于解决构造方法传入集合时,final变量的赋值问题
- 初始化列表会在构造方法体执行之前执行
- 使用逗号分隔初始化表达式
- 初始化列表常用于设置final变量的值
class Girle{
String name;
int age;
final String gender;
Girle.withMap(Map map) : gender = map["gender"]{
this.name = map["name"];
this.age = map["age"];
}
void work(){
print("Name is $name,Age is $age,Gender is $gender,She is working...");
}
}
var map = {"name":"tom","age":12,"gender":"女"};
var girle = Girle.withMap(map);
girle.work();
八、静态成员及对象操作符的使用
1、静态成员
- 使用static关键字来实现类级别的变量和函数
- 静态成员不能方位非静态成员,非静态成员可以访问静态成员
- 类中的常量需要使用static const声明
class Page{
static const int maxPage = 10;
static int currentPage = 1;
static void up(){
currentPage++;
print("currentPage = $currentPage");
}
static void down(){
currentPage--;
print("currentPage = $currentPage");
}
}
Page.up();//currentPage = 2
Page.down();//currentPage = 1
2、对象操作符
条件成员访问:?.
相当于在执行之前进行判空操作,如果为null则不再执行
var person;
person?.age = 12;
此时如果不适用?.则会crash
类型转换:as
person = "";
person = Person();
(person as Person).age = 12;
是否指定类型:"is & is! "用于判断对象的class
if(person is Person){
person.age = 12;
}
级联操作
person..name = "小李"
..age = 26
..work();
九、对象call方法
如果类实现了call()方法,则该类的对象化可以作为方法使用
class Animal{
String call(name,age)=>"Name is $name, age is $age";
}
var animal = Animal();
print(animal("小猫",1));//Name is 小猫, age is 1
十、继承、继承中的构造函数
- 键字extends继承一个类
- 子类会继承父类可见的属性和方法,不会继承构造方法
- 子类能够复写父类的方法、getter和setter
- 单继承
class Person {
String name;
int age;
String _birthday;
bool get isAdult => age > 18;
void run(){
print("Person run...");
}
}
class Student extends Person{
@override
bool get isAdult => age > 15;
@override
void run(){
print("Student run...");
}
@override
String toString(){
return("Student toString");
}
void study(){
print("Student study...");
}
}
- 继承中的构造方法
- 子类的构造方法默认会调用父类无名无参的构造方法
- 如果父类没有无名午餐的构造方法,则需要显示调用父类构造方法
- 在构造方法参数后使用:显示调用父类构造方法
class Person {
String name;
int age;
String _birthday;
bool get isAdult => age > 18;
Person(this.name);
Person.withName(this.name);
void run(){
print("Person run...");
}
}
class Student extends Person{
Student(String name) : super(name);
}
- 构造方法执行顺序
- 父类的构造方法在子类构造方法体开始执行的位置调用
- 如果有初始化列表,初始化列表会在父类构造方法之前执行
class Person {
String name;
int age;
bool get isAdult => age > 18;
Person(this.name);
Person.withName(this.name);
void run(){
print("Person run...");
}
}
class Student extends Person{
final String gender;
Student(String name,String g) : gender = g,super(name);
}
十一、抽象类
- 抽象类使用abstract标识,不能直接被实例化
- 抽象方法不用abstract修饰,无实现
- 抽象类可以没有抽象方法
- 有抽象方法的类一定得声明为抽象类
abstract class Person{
void run();
}
class Student extends Person{
@override
void run(){
print("run...");
}
}
十二、接口
- 类和接口是统一的,类就是接口
- 每个类都隐式定义了一个包含所有实例成员的接口
- 如果是复用已有类的实现,使用继承(extends)
- 如果只是使用已有类的外在行为,使用接口(implements)
class Person {
String name;
int age;
void run(){
print("Person run...");
}
}
class Student implements Person{
@override
String name;
@override
int age;
@override
void run(){
print("run...");
}
}
建议使用抽象类作为接口
abstract class Person{
void run();
}
class Student implements Person{
@override
void run(){
print("run...");
}
}
十三、Mixins,操作符的覆写
1、Mixins
- Mixins类似于多继承,是在多类继承中重用一个类代码的方式,Mixin不能直接使用,必须配合继承
- 作为Mixin的类不能有显示声明构造函数
- 作为Mixin的类智能继承自Object
- 使用关键字with连接一个或多个mixin
顺序问题
- 如果2个或多个超类拥有相同签名的A方法,那么子类会以继承的最后一个超类中的A方法为准。
- 若子类也重写了改方法也已子类为准
- 优先级顺序是:子类自己实现>Mixin>继承,如果有多个Mixin,则已最后的Mixin为主
class A {
String getMessage() => 'A';
}
class B {
String getMessage() => 'B';
}
class P {
String getMessage() => 'P';
}
class AB extends P with A, B {}
class BA extends P with B, A {}
class C extends P with B, A {
String getMessage() => 'C'; //优先级最高的是在具体类中的方法。
}
//关系连接:implements实现、extends继承、with混入
class CC extends P with B implements A {
}
var cc = CC();
print(cc.getMessage());//=>B
使用mixin进行类组合
abstract class Person{
String name;
int age;
void run();
}
class Animal{
void eat(){
print("eat...");
}
}
//mixin on的使用,使用这个mixin的class必须继承自Animal
mixin Boy on Animal implements Person{
@override
String name;
@override
int age;
@override
void run(){
print("Person run...");
}
void playBall(){
print("playBall...");
}
}
mixin Girle implements Person {
@override
String name;
@override
int age;
@override
void run(){
print("Person run...");
}
void dance(){
print("dance...");
}
}
class Cat{
void eat(){
print("eat...");
}
}
此时我们可以使用快捷方式组合class
class A = Cat with Girle;
var a = A();
a.run();
2、操作符的覆写
- 操作符覆写
- 覆写需要在类中定义
返回类型 operator操作符(参数1、参数2.....){
实现体
return 返回值
}
class Person {
int age;
bool operator > (Person person){
return this.age > person.age;
}
}
var p1= Person();
p1.age = 18;
var p2= Person();
p2.age = 13;
print(p1>p2);//ture
十四、方法
1、方法定义
- 法也是对象,并且有具体类型Function
- 返回类型、参数类型都可以省略
- 箭头语法:=> expr 是{return expr;}缩写。只适用于一个表达式
- 方法都有返回值。如果没有制定,默认return null左后一句执行
//方法也是对象,并且有具体类型Function
String getPerson(String name, int age){
return "名字:$name,年龄:$age";
}
printPerson(name,age){
print("名字:$name,年龄:$age");
}
//=>语法
getPerson1(name, age) => "名字:$name,年龄:$age";
print(getPerson('张三',12));
printPerson('张三',12);
print(getPerson1('张三',12));
2、可选参数
- 可选命名参数:{param1,param2,…}
- 可选位置参数:[param`,param2,…]
//1、可选命名参数{param1,...}
printPersionOptional1(name,{age,gender}) => "名字:$name,年龄:$age,性别:$gender";
//2、可选位置参数[param1,...]
printPersionOptional2(name,[age,gender]) => "名字:$name,年龄:$age,性别:$gender";
注意:可选参数必须在具体参数之后!!!
3、默认参数
- 使用=在可选参数指定默认值
- 默认值只能是编译时常量
//默认参数
printPersionOptionalDefault(name,{age=12,gender="男"}) => "名字:$name,年龄:$age,性别:$gender";
归纳代码:
//要达到可选命名参数的用法,那就在定义函数的时候给参数加上 {}
void enable1Flags({bool bold, bool hidden}) => print("$bold , $hidden");
//定义可选命名参数时增加默认值
void enable2Flags({bool bold = true, bool hidden = false}) => print("$bold ,$hidden");
//可忽略的参数在函数定义时用[]符号指定
void enable3Flags(bool bold, [bool hidden]) => print("$bold ,$hidden");
//定义可忽略参数时增加默认值
void enable4Flags(bool bold, [bool hidden = false]) => print("$bold ,$hidden");
//可选命名参数函数调用
enable1Flags(bold: true, hidden: false); //true, false
enable1Flags(bold: true); //true, null
enable2Flags(bold: false); //false, false
//可忽略参数函数调用
enable3Flags(true, false); //true, false
enable3Flags(true,); //true, null
enable4Flags(true); //true, false
enable4Flags(true,true); // true, true
4、对象方法
- 方法可作为对象赋值给其他变量
- 方法可作为参数传递给其他方法
void printHrello(){
print("Hello");
}
void printDoubleNumber(num){
print(num*5);
}
List listTimes(list,times(str)){
for(var index = 0; index < list.length; index ++){
list[index] = times(list[index]);
}
return list;
}
List listTimes1(list){
var fun = (str)=>str*3;
for(var index = 0; index < list.length; index ++){
list[index] = fun(list[index]);
}
return list;
}
times(str) => str*3;
Function func = printHrello;
func();
var list = [1,2,3,4];
//forEach接收一个Function类型的参数
list.forEach(print);
list.forEach(printDoubleNumber);
print(listTimes(['a','b','c','d'],times));
执行结果:
Hello
1
2
3
4
5
10
15
20
[aaa, bbb, ccc, ddd]
5、匿名方法
匿名方法特征:
- 可赋值给变量,通过变量进行调用
- 可在其他方法中直接调用或传递给其他方法
//匿名方法
var func = (str){
print('======= $str');
};
func("Hlelo");
//匿名方法直接执行
((){
print('=======');
})();
print(listTimes(['a','b','c','d'],(str)=>str*5));
print(listTimes1(['a','b','c','d']));
6、闭包
- 闭包是一个方法(对象)
- 闭包定义在其他方法内部
- 闭包能够访问外部方法内的局部变量,并持有其状态
a(){
int count = 0;
printCount(){
print(count++);
}
return printCount;
}
var func = a();
func();
func();
func();
func();
执行结果:
0
1
2
3
另一种写法:
a(){
int count = 0;
// printCount(){
// print(count++);
// }
return (){
print(count++);
};
}
执行结果仍然是:
0
1
2
3
十五、枚举
1、枚举是一种有穷序列集的数据类型
2、使用关键字enmu定义一个枚举
3、常用于代替常量,控制语句等
enum Season{
spring,
summer,
autumn,
winter
}
void main() {
var currentSeason = Season.spring;
switch(currentSeason){
case Season.spring:
print("1-3月");
break;
case Season.summer:
print("4-6月");
break;
case Season.autumn:
print("7-9月");
break;
case Season.winter:
print("10-12月");
break;
}
}
index从0开始,依次累加
var currentSeason = Season.spring;
print(currentSeason.index);//0
注意:Dart中枚举不能指定原始值,不能添加方法!!
十六、泛型
1、Dart中类型是可选的,可使用泛型限定类型
2、使用泛型能够有效的减少代码重复
类的泛型:在类名后定义
void main() {
var utils1 = new Utils1<int>();
utils1.put(1 );
}
class Utils1<T>{
T element;
void put(T element){
this.element = element;
}
}
方法的泛型:在方法名后定义
void main() {
var utils2 = new Utils2();
utils2.put<String>("1");
}
class Utils2{
void put<T>(T element){
print(element);
}
}
网友评论