🥇🚩Приложения Flutter разрабатываются с использованием языка Dart, который является объектно-ориентированным, определяемым классом языком с одним наследованием. Его синтаксис похож на язык C, его можно перевести в JavaScript, и он поддерживает интерфейсы, примеси, абстрактные классы, конкретные дженерики и необязательные типы.
"
Я верю, что эта статья обязательно принесет вам пользу 👉
предисловие
下面这一段是笔者从Dart官网摘抄过来的,笔者认为在学习Dart之前,先要了解以下Dart相关概念:
-
Все, что хранится в переменной, является объектом, и все объекты являются экземплярами соответствующего класса. И числа, и функции, и null являются объектами. Все объекты наследуются от класса Object.
-
Хотя Dart строго типизирован, Dart может выводить типы, поэтому аннотации типов необязательны. Если вы хотите явно указать, что тип не требуется, вам нужно использовать специальный динамический тип.
-
Dart поддерживает дженерики, такие как List (список целых чисел) или List (список объектов любого типа).
-
Dart поддерживает функции верхнего уровня, такие как
main()
), одна и та же функция привязана к классу или объекту (статическая функция и функция экземпляра соответственно). А также поддержка создания функций (вложенных или локальных) внутри functions. -
Dart поддерживает переменные верхнего уровня, которые также связаны с классами или объектами (статические переменные и переменные экземпляра). Переменные экземпляра иногда называют полями или свойствами.
-
В отличие от Java, в Dart нет ключевых слов «публичный», «защищенный» и «частный». Если идентификатор начинается с символа подчеркивания (_), он является частным для библиотеки.
-
Идентификаторы начинаются с буквы или символа подчеркивания (_), за которыми следует любая комбинация букв и цифр.
-
Синтаксис Dart состоит из выражений (со значением времени выполнения) и операторов (без значения времени выполнения). Например, условие условного выражения ?expr1 : expr2 может иметь значение expr1 или expr2 . Сравните это с оператором if-else, который не имеет значения. Оператор обычно содержит одно или несколько выражений, тогда как выражения не могут непосредственно содержать операторы.
-
Всплывающие подсказки Dart имеют два типа проблем: предупреждения и ошибки. Предупреждения просто указывают на то, что код может работать некорректно, но не препятствуют выполнению программы. Ошибка может быть ошибкой времени компиляции или ошибкой времени выполнения. Ошибка времени компиляции препятствует выполнению кода; ошибка времени выполнения заставляет код вызывать [исключение] (#exception) во время выполнения.
Соглашения об именах дротиков
основной() Программа начинает выполнение функции, которая является определенной, обязательной функцией верхнего уровня.
Переменные дротика
Dart本身是一个强类型语言,任何变量都是有确定类型的。
1. Создайте переменную с помощью var и инициализируйте ее
var name = 'lisa'; //name 变量的类型被推断为 String
В Dart, когда переменная объявлена с помощью var,Dart在编译时会根据第一次赋值数据的类型来推断其类型,编译结束后其类型就已经被确定。
Например, указанное выше имя было определено как тип String, и другие типы не могут быть скопированы, иначе будет сообщено об ошибке. Но вы также можете изменить тип переменной, указав тип. Например:
name = 123; //报错
name = '张三' // 不报错
2. Явно объявите типы, которые можно вывести:
Например: при использовании String определяется, что name имеет тип String.
String name = '张三';
3. динамический. Его тип можно изменить по желанию.
Если вы хотите явно указать, что тип не требуется, вам нужно использовать специальный динамический тип.
4. Значение по умолчанию - значение по умолчанию для неинициализированной переменной равно null.
Даже если переменная является числом, значение по умолчанию равно null, потому что все в Dart является объектом, и числа не являются исключением.
Константы дротика:
Переменные, которые никогда не изменяются во время использования, могут быть final или const вместо var или других типов.
使用final或者const修饰的变量,变量类型可以省略.
final
final name = 'Bob';
final String nickname = 'Bobby';
const
const bar = 1000000;
const double atm = 1.01325 * bar;
Разница между final и const:
final a=new DateTime.now();
print(a); //2019-05-10 15:59:02.966122
//const a=new DateTime.now(); //报错了
Разница между ними заключается в том, что переменная const является константой времени компиляции, а переменная final инициализируется при первом использовании.
Правила именования дротиков:
-
Имена переменных должны состоять из цифр, букв, символов подчеркивания и знаков доллара ($).
-
Примечание. Идентификаторы не могут начинаться с цифры.
-
Идентификаторы не могут быть зарезервированными словами и ключевыми словами.
-
Имена переменных чувствительны к регистру, например: age и Age — разные переменные. В практическом применении также рекомендуется не использовать регистр слова для различения двух переменных.
-
Идентификаторы (имена переменных) должны иметь значение имени: для имен переменных рекомендуются существительные, а для имен методов – глаголы.
Типы данных дротика
Тип строки
1. Несколько способов определения строк
var str1='this is str1';
String str1='this is str1';
2. Конкатенация строк
String str1='你好';
String str2='Dart';
print("$str1 $str2"); //你好Dart
//或者使用 +运算符
print(str1+str2); //你好Dart
- Используйте три последовательных одинарных кавычки или три двойных кавычки, чтобы создать многострочный строковый объект:
Числовой тип
Числовой тип делится на тип int и тип double.
И int, и double являются подтипами num. Тип num включает основные операции +, -, / и *, а также функциональные методы, такие как abs(), ceil(), floor() и т. д.
1. int должен быть целым числом
int a=123;
a=45;
print(a);
2, double может быть либо целым числом, либо типом с плавающей запятой.
double b=23.5;
b=24;
print(b);
логический тип
Dart использует тип bool для представления логических значений. Dart только литералы true и false являются булевыми.
bool flag1=true;
print(flag1);
bool flag2=false;
print(flag2);
bool flag=true;
if(flag){
print('真');
}else{
print('假');
}
Тип коллекции списка
Массив в Dart — это объект списка, обычно называемый List.
1. Первый способ определить список
var arr1=['aaa','bbbb','cccc'];
print(arr1);
print(arr1.length);
print(arr1[1]);
2. Второй способ определения списка
Тип элемента не определен.
var arr2=new List();
arr2.add('张三');
arr2.add('李四');
arr2.add('王五');
print(arr2);
print(arr2[2]);
//也可以使用下面这种方法
var arr3=new List<dynamic>();
arr3.add('张三');
arr3.add(123);
print(arr3);
3. Определите указанный тип спискаКаждый элемент указанного списка имеет тип String.
main() {
var arr3=new List<String>();
arr3.add('张三');
arr3.add('lisa');
print(arr3);
}
Тип карты
В общем, карта — это объект, используемый для связывания ключей и значений. ключи и значения могут быть объектами любого типа. Ключ может появиться только один раз в объекте карты. Но значение может появляться несколько раз. Карты в Dart реализованы через литералы карты и типы карт.
Первый способ определить карту
var person={
"name":"张三",
"age":20,
"work":["程序员","送外卖"]
};
print(person);
print(person["name"]);
print(person["age"]);
print(person["work"]);
Второй способ определения Map
var p=new Map();
p["name"]="李四";
p["age"]=22;
p["work"]=["程序员","送外卖"];
print(p);
print(p["age"]);
Тип набора
Set — это коллекция, которая не имеет порядка и не может повторяться, поэтому значение не может быть получено по индексу
var s=new Set();
s.add('香蕉');
s.add('苹果');
s.add('苹果');
print(s); //{香蕉, 苹果}
print(s.toList()); //[香蕉, 苹果]
List myList=['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果'];
var s=new Set();
Может использоваться для дедупликации массива
List myList=['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果'];
var s=new Set();
s.addAll(myList);
print(s); //{香蕉, 苹果, 西瓜}
print(s.toList()); //[香蕉, 苹果, 西瓜]
другие типы
Runes
Rune — это строка в кодировке UTF-32. Он может преобразовывать текст в смайлики или представлять определенный текст.
Symbols
Объекты символов представляют собой операторы или идентификаторы, объявленные в программах Dart.
Общие операторы Dart
арифметические операторы
int a=13;
int b=5;
print(a+b); //加
print(a-b); //减
print(a*b); //乘
print(a/b); //除
print(a%b); //取余
print(a~/b); //取整
оператор отношения
int a=5;
int b=3;
print(a==b); //判断是否相等
print(a!=b); //判断是否不等
print(a>b); //判断是否大于
print(a<b); //判断是否小于
print(a>=b); //判断是否大于等于
print(a<=b); //判断是否小于等于
оператор присваивания
Используйте = для присвоения значений переменным. При использовании оператора ??= он назначается только в том случае, если присваиваемая переменная имеет значение null.
int b=6;
b??=23;
print(b); //6
int b;
b??=23;
print(b); //23
если a пусто, то b=10;
var a=22;
var b= a ?? 10;
print(b); //22
преобразование типов
Number类型转换成String类型 toString()
String类型转成Number类型 int.parse()
преобразовать строку в число
String str='123';
var myNum=int.parse(str);
print(myNum is int);
String str='123.1';
var myNum=double.parse(str);
print(myNum is double);
String price='12';
var myNum=double.parse(price);
print(myNum);
print(myNum is double);
Об этом можно судить по try...catch
String price='';
try{
var myNum=double.parse(price);
print(myNum);
}catch(err){
print(0);
}
Преобразование чисел в строки
var myNum=12;
var str=myNum.toString();
print(str is String);
Преобразование других типов в логические значения
//isEmpty:判断字符串是否为空
var str='';
if(str.isEmpty){
print('str空');
}else{
print('str不为空');
}
var myNum=123;
if(myNum==0){
print('0');
}else{
print('非0');
}
var myNum;
if(myNum==0){
print('0');
}else{
print('非0');
}
var myNum;
if(myNum==null){
print('空');
}else{
print('非空');
}
Объяснение типов сбора дротиков
Часто используемые свойства и методы в списке:
Свойства в списке:
List myList=['香蕉','苹果','西瓜'];
print(myList.length);
print(myList.isEmpty);
print(myList.isNotEmpty);
print(myList.reversed); //对列表倒序排序
var newMyList=myList.reversed.toList();
print(newMyList);
Методы в списке:
List myList=['香蕉','苹果','西瓜'];
myList.add('桃子'); //增加数据 增加一个
myList.addAll(['桃子','葡萄']); //拼接数组
print(myList);
print(myList.indexOf('苹x果')); //indexOf查找数据 查找不到返回-1 查找到返回索引值
myList.remove('西瓜'); //删除 传入具体值
myList.removeAt(1); //删除 传入索引值
print(myList);
myList.fillRange(1, 2,'aaa'); //修改
myList.fillRange(1, 3,'aaa');
myList.insert(1,'aaa'); // 指定位置插入 插入一个
myList.insertAll(1, ['aaa','bbb']); //插入 多个 指定位置插入List
var str=myList.join('-'); //list转换成字符串
print(str);
print(str is String); //true
var list=str.split('-'); // 字符串转化成List
var arr = (11,22,33);
var arr2 = arr.toList(); //其他类型转换成List
遍历List的方法:forEach map where any every,用法和ES6一样,此处不再赘述。
Set:
Основная функция его использования — удалить повторяющееся содержимое массива; Set — это коллекция, которая не имеет порядка и не может повторяться, поэтому значение нельзя получить по индексу;
var s=new Set();
s.add('香蕉');
s.add('苹果');
s.add('苹果');
print(s); //{香蕉, 苹果}
print(s.toList());
List myList=['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果'];
var s=new Set();
s.addAll(myList);
print(s);
print(s.toList());
s.forEach((value)=>print(value));
Карта: карта представляет собой неупорядоченную пару ключ-значение:
Общие свойства:
Map person={
"name":"张三",
"age":20,
"sex":"男"
};
print(person.keys.toList());
print(person.values.toList());
print(person.isEmpty); //是否为空
print(person.isNotEmpty); //是否不为空
Общий метод:
Map person={
"name":"张三",
"age":20,
"sex":"男"
};
person.addAll({ //合并映射 给映射内增加属性
"work":['敲代码','送外卖'],
"height":160
});
print(person);
person.remove("sex"); //删除指定key的数据
print(person);
print(person.containsValue('张三')); //查看映射内的值 返回true/false
person.forEach((key,value){
print("$key---$value");
});
Дартс функции
Dart — настоящий объектно-ориентированный язык, даже функции в нем являются объектами и имеют свой тип Function.
пользовательский метод
нет возвращаемого значенияКлючевое слово void перед ним означает, что метод не имеет возвращаемого значения.
void printInfo(){
print('我是一个自定义方法');
}
Возвращает значение типа int
int getNum(){
var myNum=123;
return myNum;
}
тип возвращаемой строки
String printUserInfo(){
return 'this is str';
}
Тип возвращаемого списка
List getList(){
return ['111','2222','333'];
}
основная функция
Любое приложение должно иметь функцию main() верхнего уровня, которая служит точкой входа для служб приложения. Возвращаемое значение функции main() пусто, а параметр является необязательным списком.
void main(){
print('调用系统内置的方法');
printInfo();
var n=getNum();
print(n);
print(printUserInfo());
print(getList());
print(getList());
}
область действия метода
void get(){
aaa(){
print(getList());
print('aaa');
}
aaa();
}
// aaa(); 错误写法
get(); //调用方法
}
параметр метода
Определите метод для нахождения суммы всех чисел от 1 до этого числа, и возвращаемое значение имеет тип int.
int sumNum(int n){ //接收的参数必须事int类型,否则报错
var sum=0;
for(var i=1;i<=n;i++)
{
sum+=i;
}
return sum;
}
var sum=sumNum(5);
Определите метод, а затем распечатайте информацию о пользователе, возвращаемое значение имеет тип String, а передаваемые параметры имеют тип String и int.
String printUserInfo(String username,int age){ //行参
return "姓名:$username---年龄:$age";
}
print(printUserInfo('张三',20)); //实参
Определите метод с необязательными параметрами
Оберните набор параметров функции, помеченных [] как необязательные позиционные параметры, и поместите в конец списка параметров:
String printUserInfo(String username,[int age]){ //行参
if(age!=null){
return "姓名:$username---年龄:$age";
}
return "姓名:$username---年龄保密";
}
print(printUserInfo('张三',21)); //实参
print(printUserInfo('张三'));
Определить метод с параметрами по умолчанию
Если вы не передаете необязательные параметры при вызове этого метода, вы можете использовать параметры по умолчанию.
String printUserInfo(String username,[String sex='男',int age]){ //行参
if(age!=null){
return "姓名:$username---性别:$sex--年龄:$age";
}
return "姓名:$username---性别:$sex--年龄保密";
}
print(printUserInfo('张三'));
print(printUserInfo('小李','女'));
print(printUserInfo('小李','女',30));
Метод определения именованного параметра
При определении функции используйте {param1, param2, …} в конце списка параметров, чтобы указать именованные параметры. Например:
При вызове функции с ее помощью можно указать именованные параметры. Например: paramName: значение
String printUserInfo(String username,{int age,String sex='男'}){ //行参
if(age!=null){
return "姓名:$username---性别:$sex--年龄:$age";
}
return "姓名:$username---性别:$sex--年龄保密";
}
print(printUserInfo('张三',age:20,sex:'未知'));
Отличие методов с именованными параметрами от методов с необязательными параметрами:
- Методы с именованными параметрами используют {};
- Необязательные параметры используют [];
- Методы именованных параметров должны передавать значения в соответствии с именами полей формальных параметров;
可选参数可以是命名参数或者位置参数,但一个参数只能选择其中一种方式修饰。
Функции — это объекты первого класса.
Функция может быть использована в качестве аргумента другой функции. Например:
//方法
fn1(){
print('fn1');
}
//方法
fn2(fn){
fn();
}
//调用fn2这个方法 把fn1这个方法当做参数传入
fn2(fn1);
анонимный метод
Большинство функций имеют имена, такие как main() и getInfo(). Также возможно создавать функции без имен, которые называются анонимными функциями.
Анонимные функции и именованные функции выглядят одинаково — параметры могут быть переданы в круглых скобках, а параметры могут быть разделены.
var printNum=(int n, int m){
print(m*n);
};
printNum(12,20); //240
самоисполняющийся метод
((int n){
print(n);
print('我是自执行方法');
})(12);
рекурсия метода
Запрос суммы значений в пределах 100
var sum=0;
fn(int n){
sum+=n;
if(n==0){
return;
}
fn(n-1);
}
fn(100);
print(sum);
Закрытие
Замыкание — это функциональный объект, который может обращаться к переменным в своей лексической области видимости, даже если функциональный объект вызывается за пределами своей исходной области.
/// 返回一个函数,返回的函数参数与 [addBy] 相加。
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
void main() {
// 创建一个加 2 的函数。
var add2 = makeAdder(2);
// 创建一个加 4 的函数。
var add4 = makeAdder(4);
print(add2(3) == 5); //true
print(add4(3) == 7); //true
}
Занятия в дартс
Dart所有的东西都是对象,所有的对象都继承自Object类。
Dart — это объектно-ориентированный язык, использующий классы и одиночное наследование, все объекты являются экземплярами классов, а все классы — подклассами Object.
Определение классов в Dart Использование классов
class Person{
String name="张三";
int age=23;
void getInfo(){
// print("$name----$age");
//等同于下面
print("${this.name}----${this.age}");
}
void setInfo(int age){
this.age=age;
}
}
void main() {
//实例化类
Person p1=new Person();
print(p1.name); //张三
p1.setInfo(28);
p1.getInfo(); //张三----28
}
Конструктор по умолчанию для классов в Dart
определить конструктор по умолчанию
class Person{
String name='张三';
int age=20;
//默认构造函数
Person(){
print('这是构造函数里面的内容 这个方法在实例化的时候触发');
}
void printInfo(){
print("${this.name}----${this.age}");
}
}
void main() {
//实例化类
Person p1=new Person();
print(p1.name);
p1.printInfo();
}
Передать аргументы конструктору
class Person{
String name;
int age;
//默认构造函数
Person(String name,int age){
this.name=name;
this.age=age;
}
void printInfo(){
print("${this.name}----${this.age}");
}
}
void main() {
//实例化类
Person p1=new Person('张三',20);
print(p1.name); //张三
p1.printInfo(); //张三----20
}
Сокращенный метод конструктора:
class Person{
String name;
int age;
//默认构造函数的简写
Person(this.name,this.age);
void printInfo(){
print("${this.name}----${this.age}");
}
}
void main() {
//实例化类
Person p1=new Person('张三',20);
print(p1.name); //张三
p1.printInfo(); //张三----20
}
Именованные конструкторы в Dart
В dart есть только один конструктор по умолчанию, но именованных конструкторов может быть несколько.
class Person{
String name;
int age;
//默认构造函数的简写
Person(this.name, this.age);
//我是命名构造函数
Person.now(){
print('我是命名构造函数');
}
//给命名构造函数传参
Person.setInfo(String name, int age){
this.name=name;
this.age=age;
}
void printInfo(){
print("${this.name}----${this.age}");
}
}
void main() {
Person p1=new Person('张三', 20); //默认实例化类的时候调用的是 默认构造函数
Person p2=new Person.now(); //命名构造函数
Person p3=new Person.setInfo('李四',30);
p1.printInfo(); //张三----20
p3.printInfo(); //李四----30
}
Частные методы и частные свойства в Dart
Dart отличается от других объектно-ориентированных языков тем, что в Data нет общедоступного частного защищенного.Эти модификаторы доступа соответствуют
Но мы можем использовать _, чтобы определить свойство или метод как закрытый.
新建一个单独的 Animal类
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(); //类里面方法的相互调用
}
}
// вызов приватного метода
import 'lib/Animal.dart';
void main(){
Animal a=new Animal('小狗', 3);
print(a.getName());
a.execRun(); //间接的调用私有方法
}
Использование модификаторов getter и setter в классах
class Rect{
num height;
num width;
Rect(this.height,this.width);
get area{
return this.height*this.width;
}
set areaHeight(value){
this.height=value;
}
}
void main(){
Rect r=new Rect(10,4);
// print("面积:${r.area()}");
r.areaHeight=6;
print(r.area); //24
}
Инициализировать переменные экземпляра в Dart
В Dart мы также можем инициализировать переменные экземпляра перед запуском тела конструктора.
class Rect{
int height;
int width;
Rect():height=2,width=10{
print("${this.height}---${this.width}"); //2---10
}
getArea(){
return this.height*this.width;
}
}
void main(){
Rect r=new Rect();
print(r.getArea()); //10
}
Dart класс реализует несколько интерфейсов
Определите два абстрактных класса A и B. Свойства и методы, определенные в абстрактном классе, должны быть реализованы в интерфейсе.
abstract class A{
String name;
printA();
}
abstract class B{
printB();
}
class C implements A,B{
@override
String name;
@override
printA() {
print('printA');
}
@override
printB() {
// TODO: implement printB
return null;
}
}
void main(){
C c=new C();
c.printA(); //printA
}
миксины в дарте
В Dart вы можете использовать примеси для достижения функций, подобных множественному наследованию.
Из-за условий, используемых примесями [версия Dart2.x]:
1. Классы как примеси могут наследоваться только от Object и не могут наследоваться от других классов;
2. Классы как примеси не могут иметь конструкторов;
3. Класс может примешивать несколько классов примесей;
4. Миксины ни в коем случае не наследование или интерфейсы, а совершенно новая функция
class A {
String info="this is A";
void printA(){
print("A");
}
}
class B {
void printB(){
print("B");
}
}
class C with A,B{
}
void main(){
var c=new C();
c.printA();
c.printB();
print(c.info);
}
Статические операторы-члены классов в наследовании классов Dart
Статические члены в классах Dart Статические методы
Статические элементы в Dart:
1. Используйте ключевое слово static для реализации переменных и функций уровня класса.
2. Статические методы не могут получить доступ к нестатическим членам, а нестатические методы могут получить доступ к статическим членам.
Определите класс со статическими свойствами и статическими методами
class Person {
static String name = '张三';
static void show() {
print(name);
}
}
main(){
print(Person.name);
Person.show();
}
Операторы объектов в Dart
- Условные операторы (понять)
- как преобразование типа
- это типовое суждение
- .. каскадная работа
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
?Условный оператор
Если p существует, вызовите метод printInfo.
Person p=new Person('张三', 20);
p?.printInfo();
это тип суждения
Person p=new Person('张三', 20);
if(p is Person){
p.name="李四";
}
p.printInfo();
print(p is Object);
как преобразование типа
p1=new Person('张三1', 20);
// p1.printInfo();
(p1 as Person).printInfo();
.. каскадные операции (цепочка)
Person p1=new Person('张三1', 20);
p1.printInfo();
p1.name='张三222';
p1.age=40;
p1.printInfo();
等同于
Person p1=new Person('张三1', 20);
p1.printInfo();
p1..name="李四"
..age=30
..printInfo();
Наследование класса Dart — простое наследование
Наследование классов в Dart:
1. Подкласс использует ключевое слово extends для наследования родительского класса.
2. Подкласс унаследует свойства и методы, видимые в родительском классе, но не унаследует конструктор.
3. Подклассы могут переопределять геттеры и сеттеры родительского класса.
class Person {
String name='张三';
num age=20;
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person{
}
main(){
Web w=new Web();
print(w.name);
w.printInfo();
}
Передать аргументы конструктору родительского класса
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person{
Web(String name, num age) : super(name, age){
}
}
main(){
Web w=new Web('张三', 12);
w.printInfo();
}
Вы также можете передавать параметры своим классам при наследовании
class Web extends Person{
String sex;
Web(String name, num age,String sex) : super(name, age){
this.sex=sex;
}
run(){
print("${this.name}---${this.age}--${this.sex}");
}
}
Web w=new Web('张三', 12,"男");
w.printInfo();
Передача аргументов именованным конструкторам
class Person {
String name;
num age;
Person(this.name,this.age);
Person.xxx(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person{
String sex;
Web(String name, num age,String sex) : super.xxx(name, age){
this.sex=sex;
}
run(){
print("${this.name}---${this.age}--${this.sex}");
}
}
main(){
Web w=new Web('张三', 12,"男");
w.printInfo();
w.run();
}
Наследование класса Dart Переопределение метода родительского класса
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
work(){
print("${this.name}在工作...");
}
}
class Web extends Person{
Web(String name, num age) : super(name, age);
run(){
print('run');
}
//覆写父类的方法
@override //可以写也可以不写 建议在覆写父类方法的时候加上 @override
void printInfo(){
print("姓名:${this.name}---年龄:${this.age}");
}
@override
work(){
print("${this.name}的工作是写代码");
}
}
main(){
Web w=new Web('李四',20);
w.printInfo();
w.work();
}
Dart вызывает метод родительского класса из класса
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
work(){
print("${this.name}在工作...");
}
}
class Web extends Person{
Web(String name, num age) : super(name, age);
run(){
print('run');
super.work(); //自类调用父类的方法
}
//覆写父类的方法
@override //可以写也可以不写 建议在覆写父类方法的时候加上 @override
void printInfo(){
print("姓名:${this.name}---年龄:${this.age}");
}
}
main(){
Web w=new Web('李四',20);
// w.printInfo();
w.run();
}
Полиморфизм абстрактных классов и интерфейсы в Dart
Разница между расширением абстрактного класса и реализацией:
1. Если вы хотите повторно использовать методы абстрактного класса и использовать абстрактный метод для ограничения собственного класса, мы используем расширения для наследования абстрактного класса.
2. Если мы будем использовать только абстрактные классы в качестве стандартов, мы будем использовать инструменты для реализации абстрактных классов.
Абстрактные классы в Dart
Абстрактные классы Dart в основном используются для определения стандартов, а подклассы могут наследовать абстрактные классы или реализовывать интерфейсы абстрактных классов.
1. Абстрактный класс определяется ключевым словом abstract
2. Абстрактный метод в Dart не может быть объявлен с помощью abstract Метод без тела метода в Dart называется абстрактным методом.
3. Если подкласс наследует абстрактный класс, он должен реализовать в нем абстрактный метод
4. Если абстрактный класс реализован как интерфейс, должны быть реализованы все свойства и методы, определенные в абстрактном классе.
5. Нельзя создать экземпляр абстрактного класса, только подклассы, которые его наследуют.
abstract class Animal{
eat(); //抽象方法
run(); //抽象方法
printInfo(){
print('我是一个抽象类里面的普通方法');
}
}
class Dog extends Animal{
@override
eat() {
print('小狗在吃骨头');
}
@override
run() {
// TODO: implement run
print('小狗在跑');
}
}
class Cat extends Animal{
@override
eat() {
// TODO: implement eat
print('小猫在吃老鼠');
}
@override
run() {
// TODO: implement run
print('小猫在跑');
}
}
main(){
Dog d=new Dog();
d.eat();
d.printInfo();
Cat c=new Cat();
c.eat();
c.printInfo();
// Animal a=new Animal(); //抽象类没法直接被实例化
}
Полиморфизм в Dart
-
Допускается присваивать указатель типа подкласса указателю типа суперкласса, и один и тот же вызов функции будет иметь разные эффекты выполнения.
-
Экземпляры подклассов назначаются ссылкам на суперклассы.
-
多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现
.
abstract class Animal{
eat(); //抽象方法
}
class Dog extends Animal{
@override
eat() {
print('小狗在吃骨头');
}
run(){
print('run');
}
}
class Cat extends Animal{
@override
eat() {
print('小猫在吃老鼠');
}
run(){
print('run');
}
}
main(){
Animal d=new Dog();
d.eat();
Animal c=new Cat();
c.eat();
}
Интерфейсы в Дарте
dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作为接口被实现。
Также используйте для реализации ключевое слово tools.
Но интерфейс dart немного странный, если реализуемый класс обычный класс, то все методы обычного класса и свойства в аннотации нужно перезаписать.
И поскольку абстрактные классы могут определять абстрактные методы, обычные классы не могут, поэтому, как правило, если вы хотите реализовать такие методы, как интерфейсы Java, обычно используются абстрактные классы.
Для определения интерфейсов рекомендуется использовать абстрактные классы.
定义一个DB库 支持 mysql mssql mongodb , mysql mssql mongodb三个类里面都有同样的方法
abstract class Db{ //当做接口 接口:就是约定 、规范
String uri; //数据库的链接地址
add(String data);
save();
delete();
}
class Mysql implements Db{
@override
String uri;
Mysql(this.uri);
@override
add(data) {
// TODO: implement add
print('这是mysql的add方法'+data);
}
@override
delete() {
// TODO: implement delete
return null;
}
@override
save() {
// TODO: implement save
return null;
}
remove(){
}
}
class MsSql implements Db{
@override
String uri;
@override
add(String data) {
print('这是mssql的add方法'+data);
}
@override
delete() {
// TODO: implement delete
return null;
}
@override
save() {
// TODO: implement save
return null;
}
}
main() {
Mysql mysql=new Mysql('xxxxxx');
mysql.add('1243214');
}
Класс в Dart реализует несколько интерфейсов и миксинов в Dart.
Класс в Dart реализует несколько интерфейсов:
abstract class A{
String name;
printA();
}
abstract class B{
printB();
}
class C implements A,B{
@override
String name;
@override
printA() {
print('printA');
}
@override
printB() {
// TODO: implement printB
return null;
}
}
void main(){
C c=new C();
c.printA();
}
миксины в дарте
Mixin 是复用类代码的一种途径, 复用的类可以在不同层级,之间可以不存在继承关系。
通过 with 后面跟一个或多个混入的名称,来 使用 Mixin 。
Поскольку условия, используемые примесями, менялись с версией Dart, вот условия для использования примесей в Dart2.x:
1. Классы как примеси могут наследоваться только от Object и не могут наследоваться от других классов;
2. Классы как примеси не могут иметь конструкторов;
3. Класс может примешивать несколько классов примесей;
4. Миксины ни в коем случае не наследование или интерфейсы, а новая фича;
class A {
String info="this is A";
void printA(){
print("A");
}
}
class B {
void printB(){
print("B");
}
}
class C with A,B{
}
void main(){
var c=new C();
c.printA();
c.printB();
print(c.info);
}
Передать параметры родительскому классу
class Person{
String name;
num age;
Person(this.name,this.age);
printInfo(){
print('${this.name}----${this.age}');
}
void run(){
print("Person Run");
}
}
class A {
String info="this is A";
void printA(){
print("A");
}
void run(){
print("A Run");
}
}
class B {
void printB(){
print("B");
}
void run(){
print("B Run");
}
}
class C extends Person with B,A{
//给父类传参
C(String name, num age) : super(name, age);
}
void main(){
var c=new C('张三',20);
c.printInfo();
c.run();
}
Типы миксинов в Dart
mixins的类型就是其超类的子类型。
class A {
String info="this is A";
void printA(){
print("A");
}
}
class B {
void printB(){
print("B");
}
}
class C with A,B{
}
void main(){
var c=new C();
print(c is C); //true
print(c is A); //true
print(c is B); //true
}
Дженерики в Дарте
通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)
Общие методы в Dart
Может возвращать данные только строкового типа
String getData(String value){
return value;
}
Поддержка как типа возвращаемой строки, так и типа int (избыточность кода)
String getData1(String value){
return value;
}
int getData2(int value){
return value;
}
Возврат как строкового, так и числового типа может решить эту проблему без указания типа.
getData(value){
return value;
}
Отсутствие указания типа приводит к отказу от проверки типа. Чего мы хотим добиться сейчас, так это того, что передается и что возвращается. Например: входящий числовой тип должен возвращать числовой тип, входящий строковый тип должен возвращать строковый тип
getData<T>(T value){
return value;
}
print(getData<int>(12)); //传入类型和返回类型一致
Общие классы в Dart
Вы можете добавлять в массив элементы типа int, а также можете добавлять элементы типа String.
class PrintClass<T>{
List list=new List<T>();
void add(T value){
this.list.add(value);
}
void printInfo(){
for(var i=0;i<this.list.length;i++){
print(this.list[i]);
}
}
}
PrintClass p=new PrintClass<int>();
p.add(12);
p.add(23);
p.printInfo();
Общие интерфейсы в Dart
Реализуйте функцию кеша данных: есть кеш файлов и кеш памяти. Кэш памяти и файловый кеш реализованы в соответствии с ограничениями интерфейса.
1. Определить общий интерфейс. Ограничения, что подклассы, которые его реализуют, должны иметь getByKey(key) и setByKey(key, value)
2. Тип значения, когда требуется setByKey, совпадает с типом, указанным при создании экземпляра подкласса.
abstract class Cache<T>{
getByKey(String key);
void setByKey(String key, T value);
}
class FlieCache<T> implements Cache<T>{
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是文件缓存 把key=${key} value=${value}的数据写入到了文件中");
}
}
class MemoryCache<T> implements Cache<T>{
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是内存缓存 把key=${key} value=${value} -写入到了内存中");
}
}
void main(){
MemoryCache m=new MemoryCache<Map>();
m.setByKey('index', {"name":"张三","age":20});
}
Асинхронность в Дарте
Dart — это язык, основанный на однопоточной модели. Dart также имеет свой собственный механизм процессов (или потоков), называемый изоляцией. Основная функция стартовой записи APP — изолировать.
В потоках Dart есть механизм цикла сообщений (цикл событий) и две очереди (очередь событий и очередь микрозадач).
-
Очередь событий содержит все входящие события: ввод-вывод, события мыши, события рисования, таймеры, сообщения между изолятами и т. д. Любые новые события (ввод-вывод, события мыши, события рисования, таймеры и изолированные сообщения) в любом изолировании будут помещаться в очередь событий и ставиться в очередь для выполнения.
-
Очередь микрозадач ставится в очередь только в очереди задач текущего изолята, и ее приоритет выше, чем у очереди событий.
Если микрозадача вставлена в событие, текущее событие может быть выполнено, и микрозадача может быть выполнена. Если нет микрозадачи, нет возможности перейти в очередь, то есть существование очереди микрозадач предоставляет Dart решение очереди задач.
Когда основной метод завершит выполнение и завершит работу, цикл обработки событий будет выполнять микрозадачи в порядке FIFO (первым поступил, первым обслужен) Когда все микрозадачи будут выполнены, он будет извлекать события из очереди событий и выполнять их. Повторяйте это до тех пор, пока обе очереди не опустеют, как показано на следующей блок-схеме:
Асинхронное выполнение
Так как же заставить ваш код выполняться асинхронно в Dart? Очень просто: просто поместите код, который будет выполняться асинхронно, в очередь микрозадач или очередь событий.
- Вы можете вызвать scheduleMicrotask, чтобы код выполнялся асинхронно как микрозадача.
scheduleMicrotask((){
print('a microtask');
});
- Вы можете вызвать Timer.run, чтобы код выполнялся асинхронно как событие.
Timer.run((){
print('a event');
});
Как и в JS, легко попасть в «ад обратных вызовов», если использовать только функции обратного вызова для асинхронного выполнения.Чтобы избежать этой проблемы, JS вводит Promise. Точно так же Dart представляет Future.
Future
Future очень похож на Promise в JavaScript и представляет возможное завершение (или сбой) асинхронной операции и представление ее результирующего значения. Проще говоря, он используется для обработки асинхронных операций.Если асинхронная обработка прошла успешно, будет выполнена успешная операция.Если асинхронная обработка не удалась, будет обнаружена ошибка или последующие операции будут остановлены. Будущее может соответствовать только одному результату: успеху или неудаче.
Чтобы использовать Future, вам нужно импортироватьdart.async
import 'dart:async';
Создайте Future, который запускается немедленно в очереди событий:
Future(() => print('立刻在Event queue中运行的Future'));
Future.then
Создается отложенная задача с помощью Future.delayed (реальный проект может быть реальной трудоемкой задачей, например сетевой запрос), то есть строка результата «привет, мир!» возвращается через 2 секунды, и тогда мы получаем затем асинхронный результат и распечатайте результат:
Future.delayed(new Duration(seconds: 2),(){
return "hi world!";
}).then((data){
print(data);
});
Future.catchError
Если в асинхронной задаче возникает ошибка, мы можем поймать ошибку в catchError, мы изменим приведенный выше пример на:
Future.delayed(new Duration(seconds: 2),(){
//return "hi world!";
throw AssertionError("Error");
}).then((data){
//执行成功会走到这里
print("success");
}).catchError((e){
//执行失败会走到这里
print(e);
});
then方法还有一个可选参数onError,我们也可以它来捕获异常:
Future.delayed(new Duration(seconds: 2), () {
//return "hi world!";
throw AssertionError("Error");
}).then((data) {
print("success");
}, onError: (e) {
print(e);
});
Future.whenComplete
Бывают случаи, когда мы сталкиваемся со сценариями, в которых что-то нужно сделать независимо от того, успешно выполняется асинхронная задача или нет.
Future.delayed(new Duration(seconds: 2),(){
//return "hi world!";
throw AssertionError("Error");
}).then((data){
//执行成功会走到这里
print(data);
}).catchError((e){
//执行失败会走到这里
print(e);
}).whenComplete((){
//无论成功或失败都会走到这里
});
Future.wait
Иногда нам нужно дождаться завершения нескольких асинхронных задач, прежде чем выполнять некоторые операции.
Мы моделируем две асинхронные задачи для сбора данных, моделируя Future.delayed, и когда обе асинхронные задачи выполняются успешно, результаты двух асинхронных задач объединяются и распечатываются.
Future.wait([
// 2秒后返回结果
Future.delayed(new Duration(seconds: 2), () {
return "hello";
}),
// 4秒后返回结果
Future.delayed(new Duration(seconds: 4), () {
return " world";
})
]).then((results){
print(results[0]+results[1]);
}).catchError((e){
print(e);
});
Async/await
Функциональность и использование async/await в Dart и async/await в JavaScript точно такие же.
Хотя метод возврата Future in the Future позволяет избежать уровней вложенности, уровень обратных вызовов все же существует.Есть ли способ выполнять асинхронные задачи, такие как написание синхронного кода, без использования обратных вызовов? Ответ да, надо использовать async/await, давайте посмотрим на код напрямую, а потом поясним, код такой:
task() async {
try{
String id = await login("alice","******");
String userInfo = await getUserInfo(id);
await saveUserInfo(userInfo);
//执行接下来的操作
} catch(e){
//错误处理
print(e);
}
}
- async используется для указания того, что функция является асинхронной, определенная функция будет возвращать объект Future, а метод then можно использовать для добавления функции обратного вызова.
- After await — это Future, что означает ожидание завершения асинхронной задачи, а затем опускаться после асинхронного завершения; await должно появиться внутри асинхронной функции.
Справочная документация
Официальная документация Дартс
Введение в язык Dart в документации Flutter
Я надеюсь увидеть здесь друзей и поставить мне палец вверх👍, ваша поддержка - самая большая поддержка для меня💪! ! !