Dart语言
上一篇文章写了flutter的编写demo,这次来介绍一下dart语言。
概述:
1、Dart是Google发布的一门开源编程语言
2、Dart初期目标是成为下一代的web开发语言
3、Dart目前已可用于全平台开发
4、Dart是一门面向对象的编程语言
应用场景:
1、Web开发
2、跨平台移动应用开发(Flutter)
3、脚本或服务端开发
安装Dart SDK
安装方法:http://www.dartdoc.cn/tools/sdk/#install
MAC:
$ brew tap dart-lang/dart
$ brew install dart --devel
VsCode安装Dart插件
1、Dart(代码高亮和代码补全)
2、Code Runner(快速运行代码)
3、vscode-icons-mac(MAC风格的文件和文件夹图标)
Hello Dart
- main方法是固定写法,它是程序入口
- print方法可以在控制台输出内容
-
通过文件选择run,可以运行文件中的main方法
// 主函数入口
void main() {
// 控制台打印
print('Hello Dart');
}
输出:Hello Dart
变量与常量
- 使用var声明变量,可以赋予不同类型的值
- 未初始化时,默认值为null
- 使用final声明一个只能赋值一次的变量
- 使用const声明常量
- 使用const声明的必须是编译期常量
代码
void main() {
var a;
print(a);
a = 10;
print(a);
a='Hello Dart';
print(a);
var b = 20;
print(b);
final c = 30;
// c = 50;
const d = 20;
// d = 50;
}
输出:
null
10
Hello Dart
20
数据类型
- 数值型-Number
- 字符串-String
- 布尔型-Boolean
- 列表-List
- 键值对-Map
- Runes、Symbols
数值型(num)
整型 Int
浮点型 double
数值型操作
- 运算符:+、 -、 *、 /、 ~/、 %
- 常用属性:isNaN、isEven、isOdd等
- 常用方法:abs()、round()、floor()、ceil()、toInt()、toDouble()
代码
void main() {
num a = 10;
a = 12.5;
int b = 20;
// b = 20.5
double c = 10.5;
// c = 30;
print(b + c); // 30.5
print(b - c); // 9.5
print(b * c); // 210.0
print(b / c); // 1.9047619047619047
print(b ~/ c); // 1
print(b % c); // 9.5
print(0.0 / 0.0); // NaN
print(b.isEven); // true
print(b.isOdd); // false
int d = 11;
print(d.isEven); // false
print(d.isOdd); // true
int e = -100;
print(e.abs()); // 100
double f = 10.5;
print(f.round()); // 11
print(f.floor()); // 10
print(f.ceil()); // 11
print(f.toInt()); // 10
print(d.toDouble()); // 11.0
}
字符串(String)
字符串创建
- 使用单引号,双引号创建字符串
- 使用三个引号或双引号创建多行字符串
- 使用r创建原始raw字符串
字符串操作
- 运算符:+、*、==、[]
- 插值表达式:${expression}
- 常用属性:length、isEmpty、isNotEmpty
常用方法
- contains(),subString()
- stratsWith(),endsWidth()
- indexOf(),lastIndexOf()
- toLowerCase(),toUpperCase()
- trim(),trimLeft(),trimRight()
- split(),replaceXXX()
代码
void main() {
String str1 = 'Hello'; // ""
String str2 = '''Hello
Dart'''; // """
print(str2);
// String str3 = 'Hello \n Dart';
String str3 = r'Hello \n Dart';
print(str3);
String str4 = "This is my favorite language";
print(str4 + "New"); // 字符串拼接
print(str4 * 5); // 字符串重复次数
print(str3 == str4); // 字符串比较
print(str4[0]); // 取所在位置的字符
int a = 1;
int b = 2;
print("a + b = ${a + b}"); // 插值表达式
print("a = $a"); // 直接取变量
print(str4.length); // 字符串长度
print(str4.isEmpty); // 判断字符串是否为空 false
print(str4.isNotEmpty); // 判断字符串是否不为空 true
print(str4.contains("This")); // 是否包含字符串
print(str4.substring(0,3)); // 字符串截取
print(str4.startsWith("a")); // 是否起始位置字符串
print(str4.endsWith("ge")); // 是否结束位置字符串
var list = str4.split(" "); // 使用空格分割字符串
print(list); // [This, is, my, favorite, language]
print(str4.replaceAll("This", "That")); // 替换字符串中符合条件的字符串
}
布尔型(bool)
- 使用bool表示布尔类型
- 布尔值只有true和false
代码
void main() {
bool isTrue = true;
bool isFalse = false;
print("Hello".isEmpty); // 非空
}
列表(List)
List(数组创建)
- 创建List:var list = [1, 2, 3];
- 创建不可变的List:var list = const[1, 2, 3];
- 构造创建:var list = new List();
常用操作
- [], length
- add(), insert()
- remove(), clear()
- indexOf(), lastIndexOf()
- sort(), sublist()
- shuffle(), asMap(), forEach()
代码
void main() {
var list1 = [1, 2, 3, "Dart", true];
print(list1); // 打印list
print(list1[2]); // 打印list索引2位置的元素
list1[1] = "Hello"; // 更改list的成员
print(list1);
var list2 = const [1, 2, 3];
// list2[0] = 5;
var list3 = new List(); // 用构造函数创建List
var list = ["Hello", "Dart"];
print(list.length); // list长度
list.add("New"); // list添加元素
print(list);
list.insert(1, "Java"); // 在指定位置插入元素
print(list);
list.remove("Java"); // 移除某一个元素
print(list);
// list.clear(); // 清空list
// print(list);
print(list.indexOf("dart1")); // 查找位置
list.sort(); // 排序
print(list);
print(list.sublist(1)); // 从指定索引位置处截取
list.forEach(print); // 循环打印list
}
集合(Map)
Map创建
- 创建Map:var language = {'first': 'Dart', 'second': 'java'};
- 创建不可变的Map:var language = const {'first': 'Dart', 'second': 'java'};
- 构造创建:var language = new Map();
常用操作
- [], length
- isEmpty(), isNotEmpty()
- Keys, values
- containsKey(), containsValue()
- remove()
- forEach()
代码
void main() {
var map1 = {"first": "Dart", 1: true, true: "2"}; // 创建map
print(map1);
print(map1["first"]); // map key值对应的value
print(map1[true]); // map key值对应的value
map1[1] = false; // map指定位置的value的修改
print(map1);
var map2 = const {1: "Dart", 2: "Java"}; // 创建不可修改的map
// map2[1] = "Python";
var map3 = new Map(); // 构造创建map
var map = {"first": "Dart", "second": "Java", "third": "Python"};
print(map.length); // map长度
// map.isEmpty;
print(map.keys); // map所有的key
print(map.values); // map所有的value
print(map.containsKey("first")); // map中是否包含first的key值
print(map.containsValue("C")); // map总是否包含C的value
map.remove("third"); // 移除key值为third的元素
print(map);
map.forEach(f); // 遍历map并调用f这个回调函数
var list = ["1", "2", "3"];
print(list.asMap()); // list转map
}
void f(key, value) {
print("key=$key,value=$value");
}
动态类型(dynamic)
- dynamic不在编译时确定类型,而是运行时确定函数类型
- var是在声明的变量在赋值的那一刻确定是什么类型
代码
void main() {
var a;
a = 10;
a = "Dart";
dynamic b = 20; // 声明动态类型变量
b = "JavaScript";
var list = new List();
list.add(1);
list.add("hello");
list.add(true);
print(list);
}
运算符
算数运算符
- 加减乘除:+, -, *, /, ~/, %
- 递增递减:++var, var++, --var, var--
代码
void main() {
int a = 10;
int b = 2;
print(a + b); // 12
print(a - b); // 8
print(a * b); // 20
print(a / b); // 5.0
print(a ~/ b); // 5
print(a % b); // 0
print(a++); // 10
print(++a); // 12
print(a--); // 12
print(--a); // 10
}
关系运算符
- 运算符:==, !=, >, <, >=, <=
- 判断内容是否相同使用==
代码
void main() {
int a = 5;
int b = 3;
print(a == b); // false
print(a != b); // true
print(a > b); // true
print(a < b); // false
print(a >= b); // false
print(a <= b); // false
String strA = "123";
String strB = "321";
print(strA == strB); // false
}
逻辑运算符
- 运算符:!, &&, ||
- 针对布尔类型运算
代码
void main() {
bool isTrue = true;
print(!isTrue); // false
bool isFalse = false;
print(isTrue && isFalse); // false
print(isTrue || isFalse); // true
String str = "";
print(!str.isEmpty); // true
}
赋值运算符
- 基础运算符:=, ??=
- 符合运算符:+=, -=, *=, /=, %=, ~/=
代码
void main() {
int a = 10;
int b;
b ??= 10; // 如果左边这个变量没有值,就把右边的值赋值给左边,否则右边的值无效,不会进行赋值操作
print(b); // 10
a += 2;
print(a); // 12
a -= b;
print(a); // 2
a *= b;
print(a); // 20
// a /= b;
a ~/= b;
print(a); // 2
a %= b;
print(a); // 2
}
条件表达式
- 三目运算符:condition ? expr1 : expr2
- ??运算符:expr1 ?? expr2
代码
void main() {
int gender = 1;
String str = gender == 0 ? "Male=$gender" : "Female=$gender";
print(str); // Female=1
String a;
String b = "Java";
String c = a ?? b;
print(c); // Java
}
控制流语句
条件语句
- if语句
- if...else if语句
- if...else if...else语句
代码
void main() {
int score = 90;
if(score >= 90) {
if(score == 100) {
print("完美");
} else {
print("优秀");
}
} else if (score > 60) {
print("良好");
} else if (score == 60) {
print("及格");
} else {
print("不及格");
}
}
循环语句
- for循环
- for...in循环
代码
void main() {
var list = [1, 2, 3, 4, 5];
for (var i = 0; i < list.length; i++) {
print(list[i]);
} // 1 2 3 4 5
for (var item in list) {
print(item);
} // 1 2 3 4 5
}
while语句
- while循环
- do...while循环
代码
void main() {
int count = 0;
while(count < 5) {
print(count++);
} // 0 1 2 3 4
do {
print(count--); // 5 4 3 2 1
} while(count > 0 && count < 5); // 先执行do里面的语句然后在判断
}
break和continue
- 终止循环:break
- 跳出当前循环:continue
代码
void main() {
var list = [1, 2, 3];
for (var item in list) {
if (item == 2) {
// break;
continue;
}
print(item); // 1 3
}
var list2 = [4, 5, 6];
for (var item1 in list) {
if (item1 == 2) {
break;
}
for (var item2 in list2) {
if (item2 == 5) {
break;
}
print(item2);
}
} // 4
}
switch...case语句
- 比较类型:num, String, 编译器常量, 对象, 枚举
- 非空case必须有一个break
- default处理默认情况
代码
void main() {
String language = "Python";
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");
} // Dart is my favorite
switch(language) {
case "Dart":
print("Dart is my favorite");
break;
Test:
case "Java":
print("Java is my favorite");
break;
case "Python":
print("Python is my favorite");
continue Test;
// break;
default:
print("None");
}
// Python is my favorite
// Java is my favorite
}
Function
方法定义
返回类型 方法名 (参数1, 参数2, ...) {
方法体...
return 返回值
}
方法特性
- 方法也是对象, 并且有具体类型Function
- 返回值类型、参数类型都可以省略
- 箭头语法:=> expr是{return expr;}缩写, 只适用于一个表达式
- 方法都有返回值, 如果没有指定, 默认return null最后一句执行
代码
void main() {
print(getPerson("张三", 18)); // name=张三,age=18
printPerson("李四", 20); // name=李四,age=20
}
int gender = 1;
getPerson(name, age) => gender == 1 ? "name=$name,age=$age" : "Test";
printPerson(name, age) {
print("name=$name,age=$age");
}
可选参数
- 可选命名参数:{param1, param2, ...}
- 可选位置参数:[param1, param2, ...]
- 如果存在具体参数, 可选参数声明, 必须在参数后面
代码
void main() {
printPerson("李四"); // name=李四,age=null,gender=null
printPerson("李四", age: 20); // name=李四,age=20,gender=null
printPerson("李四", gender: "Male"); // name=李四,age=null,gender=Male
printPerson("李四", age: 20, gender: "Male"); // name=李四,age=20,gender=Male
printPerson2("张三"); // name=张三,age=null,gender=null
printPerson2("张三", 18); // name=张三,age=18,gender=null
printPerson2("张三", 18, "Female"); // name=张三,age=18,gender=Female
}
printPerson(String name, {int age, String gender}) {
print("name=$name,age=$age,gender=$gender");
}
printPerson2(String name, [int age, String gender]) {
print("name=$name,age=$age,gender=$gender");
}
默认参数
- 使用 = 在可选参数指定默认值
- 默认值只能是编译时常量
代码
void main() {
printPerson("李四"); // name=李四,age=30,gender=Female
printPerson("李四", age: 20); // name=李四,age=20,gender=Female
printPerson("李四", gender: "Male"); // name=李四,age=30,gender=Male
}
printPerson(String name, {int age = 30, String gender = "Female"}) {
print("name=$name,age=$age,gender=$gender");
}
方法对象
- 方法可作为对象赋值给其它变量
- 方法可作为参数传递给其它方法
代码
void main() {
Function func = printHello;
func(); // Hello
var list = [1, 2, 3, 4];
list.forEach(print); // 1 2 3 4
var list2 = ["h", "e", "l", "l", "o"];
print(listTimes(list2, times)); // [hhh, eee, lll, lll, ooo]
}
void printHello() {
print("Hello");
}
List listTimes(List list, String times(str)) {
for (var i = 0;i < list.length; i++) {
list[i] = times(list[i]);
}
return list;
}
String times(str) {
return str * 3;
}
匿名方法
(参数1, 参数2, ...) {
方法体...
return 返回值
}
匿名方法特性
- 可赋值给变量, 通过变量进行调用
- 可在其它方法中直接调用或传递给其它方法
代码
void main() {
var func = (str) {
print("Hello---$str");
};
func(30); // Hello---30
// ((){
// print("Test");
// })();
var list2 = ["h", "e", "l", "l", "o"];
// var result = listTimes(list2, (str) {return str * 3;});
// print(result); // [hhh, eee, lll, lll, ooo]
print(listTimes2(list2)); // [hhh, eee, lll, lll, ooo]
}
List listTimes(List list, String times(str)) {
for (var i = 0;i < list.length; i++) {
list[i] = times(list[i]);
}
return list;
}
List listTimes2(List list) {
var func = (str) { return str * 3;};
for (var i = 0;i < list.length; i++) {
list[i] = func(list[i]);
}
return list;
}
闭包
- 闭包是一个方法(对象)
- 闭包定义在其它方法内部
- 闭包能够访问外部方法内的局部变量, 并持有其状态
代码
void main() {
var func = a();
func(); // 0
func(); // 1
func(); // 2
func(); // 3
}
a() {
int count = 0;
// printCount() {
// print(count++);
// }
return () {
print(count++);
};
}
面向对象
- 类与对象, 声明、创建以及基本特性
- 构造方法及初始化列表
- 静态成员及对象操作符的使用
类与对象
- 使用关键字class声明一个类
- 使用关键字new创建一个对象, new可省略
- 所有对象都继承于Object类
属性与方法
- 属性默认会生成getter和setter方法
- 使用final声明的属性只有getter方法
- 属性和方法通过 . 访问
- 方法不能被重载
类及成员可见性
- Dart中的可见性以library(库)为单位
- 默认情况下, 每一个Dart文件就是一个库
- 使用 _ 表示库的私有性
- 使用import导入库
代码
import 'person.dart';
void main() {
var person = new Person();
person.name = "Tom";
person.age = 20;
print(person.name); // Tom
person.work(); // Name is Tom, Age is 20, He is working...
}
// person.dart
class Person {
String name;
int age;
void work() {
print("Name is $name, Age is $age, He is working...");
}
}
计算属性
- 顾名思义, 计算属性的值是通过计算而来, 本身不存储值
- 计算属性赋值, 其实是通过计算转换到其它实例变量
代码
void main() {
var rect = new Rectangle();
rect.height = 20;
rect.width = 10;
print(rect.area); // 200
rect.area = 200;
print(rect.width); // 10.0
}
class Rectangle {
num width,height;
num get area => width * height;
set area(value) {
width = value / 20;
}
}
构造方法
- 如果没有定义构造方法, 则会有个默认构造方法
- 如果存在自定义构造方法, 则默认构造方法无效
- 构造方法不能重载
命名构造方法
- 使用命名构造方法, 可以实现多个构造方法
- 使用==类名.方法==的形式实现
代码
void main() {
var person = new Person("Tom", 20, "Male");
new Person.withName("John", "Male");
new Person.withAge(30, "Male");
}
class Person {
String name;
int age;
final String gender;
Person(this.name, this.age, this.gender);
Person.withName(this.name, this.gender);
Person.withAge(this.age, this.gender);
void work() {
print("Work...");
}
}
常量构造方法
- 如果类是不可变状态, 可以把对象定义为编译时常量
- 使用const声明构造方法, 并且所有变量都为final
- 使用const声明对象, 可以省略
代码
void main() {
const person = const Person("Tom", 20, "Male");
}
class Person {
final String name;
final int age;
final String gender;
const Person(this.name, this.age, this.gender);
void work() {
print("Work...");
}
}
工厂构造方法
- 工厂构造方法类似于设计模式中的工厂模式
- 在构造方法前添加关键字factory实现一个工厂构造方法
- 在工厂构造方法中可以返回对象
代码
class Logger {
final String name;
static final Map _cache = {};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
print(msg);
}
}
初始化列表
- 初始化列表会在构造方法体执行之前执行
- 使用逗号分隔初始化表达式
- 初始化列表常用于设置final变量的值
代码
void mian() {
var person = new Person("Tom", 20, "Male");
}
class Person {
String name;
int age;
final String gender;
Person(this.name, this.age, this.gender);
Person.withMap(Map map): gender = map["gender"] {
this.name = map["name"];
this.age = map["age"];
}
void work() {
print("Name is $name, Age is $age, He is working...");
}
}
静态成员
- 使用static关键字来实现类级别的变量和函数
- 静态成员不能访问非静态成员, 非静态成员可以访问静态成员
- 类中的常量需要使用static const声明
代码
void main() {
var page = new Page();
}
class Page {
static const int maxPage = 10;
static int currentPage = 1;
// 下滑
void scrollDown() {
currentPage = 1;
print("scrollDown...");
}
// 上滑
void scrollUp() {
currentPage++;
print("scrollUp...");
}
}
对象操作符
- 条件成员发访问:?.
- 类型转换:as
- 是否指定类型:is, is!
代码
void main() {
// Person person = new Person();
// person?.work();
// var person;
// person = "";
// person = new Person();
// (person as Person).work();
// if (person is Person) {
// person.work();
// }
new Person()..name = "Tome"
..age = 20
..work();
}
class Person {
String name;
int age;
void work() {
print("Work...$name, $age");
}
}
对象call方法
- 如果类实现了call()方法, 则该类的对象可以作为方法使用
代码
void main() {
var person = new Person();
// person.name = "Tom";
// person.age = 20;
print(person("Test", 30));
}
class Person {
String name;
int age;
// void work() {
// print("Name is $name, Age is $age");
// }
String call(String name, int age) {
return "Name is $name, Age is $age";
}
}
面向对象扩展
- 继承, 继承中的构造方法
- 抽象类
- 接口
- Mixins, 操作符的覆写
继承
- 使用关键字extends继承一个类
- 子类会继承父类可见的属性和方法, 不会继承构造方法
- 子类能够覆写父类的方法、getter和setter
- 单继承, 多态性
代码
// Person.dart
class Person {
String name;
int age;
String _birthday;
bool get isAdult => age > 18;
void work() {
print("Name is $name, Age is $age, He is working...");
}
void run() {
print("Person run...");
}
@override
String toString() {
return "Name is $name, Age is $age";
}
}
import 'person.dart';
void main() {
// var student = new Student();
// student.study();
// student.name = "Tom";
// student.age = 16;
// print(student.isAdult);
// student.run();
/**
* 多态
*/
Person person = new Student();
person.name = "Tom";
person.age = 18;
if(person is Student) {
person.study();
}
print(person);
}
class Student extends Person {
void study() {
print("Student study...");
}
@override
bool get isAdult => age > 15;
@override
void run() {
print("Student study...");
}
}
继承中的构造方法
- 子类的构造方法默认会调用父类的无名无参构造方法
- 如果父类没有无名无参的构造方法, 则需要显示调用父类构造方法
- 在构造方法参数后使用:显示调用父类构造方法
构造方法执行顺序
- 父类的构造方法在子类构造方法体开始执行的位置调用
- 如果有初始化列表, 初始化列表会在父类构造方法之前执行
代码
void main() {
var student = new Student("Tom", "Male");
print(student.name);
}
class Person {
String name;
Person(this.name);
Person.withName(this.name);
}
class Student extends Person {
int age;
final String gender;
Student(String name, String g) : gender = g, super.withName(name);
}
抽象类
- 抽象类使用abstract表示, 不能直接被实例化
- 抽象方法不用abstract修饰, 无实现
- 抽象类可以没有抽象方法
- 有抽象方法的类一定得声明为抽象类
代码
void main() {
var person = new Student();
person.run();
}
abstract class Person {
void run();
}
class Student extends Person {
@override
void run() {
print("run...");
}
}
接口
- 类和接口是同一的, 类就是接口
- 每个类都隐式的定义了一个包含所有实例成员的接口
- 如果是复用已有类的实现, 使用继承(extends)
- 如果只是使用已有类的外在行为, 使用接口(implements)
代码
void main() {
var student = new Student();
student.run();
}
// class Person {
// String name;
// int get age => 18;
// void run() {
// print("Person run...");
// }
// }
abstract class Person {
void run();
}
class Student implements Person {
@override
String name;
@override
int get age => 15;
@override
void run() {
print("Student run...");
}
}
Mixins
- Mixins类似于多继承, 是在多继承中重用一个类代码的方式
- 作为Mixin的类不能有显示声明的构造方法
- 作为Mixin的类只能继承自Object
- 使用关键with连接一个或多个mixin
代码
void main() {
var d = new D();
d.a();
}
class A {
void a() {
print("A.a()...");
}
}
class B {
void a() {
print("B.a()...");
}
void b() {
print("B.b()...");
}
}
class C {
void a() {
print("C.a()...");
}
void b() {
print("C.b()...");
}
void c() {
print("C.c()...");
}
}
class D extends A with B, C {}
abstract class Engine {
void work();
}
class OilEngine implements Engine {
@override
void work() {
print("Work with oil...");
}
}
class ElectricEngine implements Engine {
@override
void work() {
print("Work with Electric...");
}
}
class Tyre {
String name;
void run() {}
}
class Car = Tyre with ElectricEngine;
class Bus = Tyre with OilEngine;
操作符覆写
- 覆写操作符需要在类中定义
返回类型 operator 操作符(参数1, 参数2, ...) {
实现体...
return 返回值
} - 如果覆写 == , 还需要覆写对象的hashCode getter方法
可覆写的操作符
< | + | | | [] |
> | / | ^ | []= |
<= | ~/ | & | ~ |
>= | * | < | == |
- | % | >> |
代码
void main() {
var person1 = new Person(18);
var person2 = new Person(20);
print(person1 > person2);
person1.age;
print(person1['age']);
}
class Person {
int age;
Person(this.age);
bool operator > (Person person) {
print(this.age);
print(person.age);
return this.age > person.age;
}
int operator [] (String key) {
if ("age" == key) {
return age;
}
return 0;
}
}
枚举
- 枚举是一种有穷序列集的数据类型
- 使用关键字enum定义一个枚举
- 常用于代替常量, 控制语句等
Dart枚举特性
- inde从0开始, 依次累加
- 不能指定原始值
- 不能添加发方法
代码
// const spring = 0;
// const summer = 1;
// const autumn = 2;
// const winter = 3;
void main() {
var currentSeason = Season.autumn;
print(currentSeason.index);
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;
}
}
enum Season {
spring,
summer,
autumn,
winter
}
泛型
- Dart中类型是可选的, 可使用泛型限定类型
- 使用泛型能够有效的减少代码重复
泛型的使用
- 类的泛型
- 方法的泛型
代码
void main() {
var list = new List();
list.add("1");
// var utils = new Utils();
// utils.put(1);
var utils = new Utils();
utils.put(1);
}
class Utils {
void put(T element) {
print(element);
}
// void putInt(int elenment) {
// this.element = elenment;
// }
}
好了,简单就写这些。希望能够对大家有帮助,当然了,光看是不行的,还是要多多练习呀