参考:https://zhuanlan.zhihu.com/p/83387088
一.运算
1.??--------------判断前面是否是null,如果是就执行??后面的内容
//??
var num temp = exp1 ?? exp2//如果temp是null那么exp2赋值给temp
//??=
var num temp ??= exp1//如果temp是null那么exp1赋值给temp,否则temp不变
2.~/取模
3.? .. --------------级联语法,对对象的连续操作
class Person {
String name;
void run() {
print("${name} is running");
}
void eat() {
print("${name} is eating");
}
void swim() {
print("${name} is swimming");
}
}
main(List<String> args) {
final p1 = Person();
p1.name = 'why';
p1.run();
p1.eat();
p1.swim();
final p2 = Person()
..name = "why"
..run()
..eat()
..swim();
}
?其他运算和C语言一样
二. 流程控制
var names = ['why', 'kobe', 'curry'];
for (var name in names) {//这个和python有点像只不过多了个()
print(name);
}
其他和C语言一样
三.类和对象
?定义和python一样
class 类名 {
类型 成员名;
返回值类型 方法名(参数列表) {
方法体
}
}
?1.set 和 get
默认情况下,类定义的属性是可以直接被外界访问的
但是为了保证数据的安全性可以使用set和get对成员进行修改访问
main(List<String> args) {
final d = Dog("黄色");
d.setColor = "黑色";
print(d.getColor);
}
class Dog {
String color;
String get getColor {//get
return color;
}
set setColor(String color) {//set函数类型为null
this.color = color;
}
Dog(this.color);
}
2. 继承--------------extends
父类中的所有成员变量和方法都会被继承,,但是构造方法除外。
class Animal {
int age;
run() {
print('在奔跑ing');
}
}
class Person extends Animal {
}
子类的构造方法在执行前,将隐含调用父类的无参默认构造方法。如果父类没有无参默认构造方法(即父类有一个带参数的构造方法),那么子类的构造方法里必须通过super调用父类的构造方法
class Animal {
int age;
Animal(this.age);
run() {
print('在奔跑ing');
}
}
class Person extends Animal {
String name;
//:表示冒号后面的内容在前面的函数执行后会自动执行
Person(String name, int age) : name=name, super(age);
@override //override 是重载
run() {
print('$name在奔跑ing');
}
@override
String toString() {
return 'name=$name, age=$age';
}
}
?3.抽象类-------------abstract
抽线类里面只能声明函数不能定义,抽象类不能实例化
抽象类里的方法叫做抽象方法必须被子类实现
abstract class Shape {
getArea();
}
class Circle extends Shape {
double r;
Circle(this.r);
@override
getArea() {
return r * r * 3.14;
}
}
class Reactangle extends Shape {
double w;
double h;
Reactangle(this.w, this.h);
@override
getArea() {
return w * h;
}
}
?4.隐式接口---------------implements
默认情况下,定义的每个类都相当于默认也声明了一个接口,可以由其他的类来实现
在通过implements实现某个类时,类中所有的方法都必须被重新实现 (无论这个类原来是否已经实现过该方法)
abstract class Runner {
run();
}
abstract class Flyer {
fly();
}
class SuperMan implements Runner, Flyer {
@override
run() {
print('超人在奔跑');
}
@override
fly() {
print('超人在飞');
}
}
?5.Mixin混入-------------------with
mixin定义的类可以被其他类混入使用(mixin里的方法可以不被重载),使用with来进行混入
main(List<String> args) {
var superMan = SuperMain();
superMan.run();
superMan.fly();
}
mixin Runner {
run() {
print('在奔跑');
}
}
mixin Flyer {
fly() {
print('在飞翔');
}
}
// implements的方式要求必须对其中的方法进行重新实现
// class SuperMan implements Runner, Flyer {}
class SuperMain with Runner, Flyer {
}
?6.类成员和方法-----------------static
用static 关键子定义类的变量和函数,只能被类调用不能被对象调用
class Student {
String name;
int sno;
static String time;
study() {
print('$name在学习');
}
static attendClass() {
print('去上课');
}
}
?四.构造方法
机制和C++一样
1.构造方法简化
Person(String name, int age) {
this.name = name;
this.age = age;
}
// 等同于
Person(this.name, this.age);
2.?命名构造方法
当既多种不同的构造函数时,可以使用命名构造
class Person {
String name;
int age;
Person() {
name = '';
age = 0;
}
// 命名构造方法
Person.withArgments(String name, int age) {
this.name = name;
this.age = age;
}
@override
String toString() {
return 'name=$name age=$age';
}
}
// 创建对象
var p1 = new Person();
print(p1);
var p2 = new Person.withArgments('why', 18);
print(p2);
?3.重定向构造
一个构造函数调用另一个构造函数
class Person {
String name;
int age;
Person(this.name, this.age);
Person.fromName(String name) : this(name, 0);//注意这里是this
}
4.常量构造----------------const
某些情况下,我们希望传入相同的值创建的对象是同一个
在构造函数前加一个const
main(List<String> args) {
var p1 = const Person('why');//实例化的时候也要加const
var p2 = const Person('why');
print(identical(p1, p2)); // true
}
class Person {
//成员变量必须要有final修饰,因为既然是同一个对象那么他的值是不能变得
final String name;
const Person(this.name);//构造函数前加const
}
5.工厂构造方法
...没看懂
五.泛型
1.List / Map类型
可限定List / Map中的类型
//限定类型为srting
var names2 = <String>['why', 'kobe', 'james', 111]; // 最后一个报错
List<String> names3 = ['why', 'kobe', 'james', 111]; // 最后一个报错
//姓丁类型为string:string
Map<String, String> infos2 = {'name': 'why', 'age': 18}; // 18不能放在value中
var infos3 = <String, String>{'name': 'why', 'age': 18}; // 18不能放在value中
?2.类泛型
可以在类示例化的时候再指定成员变量类型,定义的时候不指定成员变量变量类型
main(List<String> args) {
Location l2 = Location<int>(10, 20);
print(l2.x.runtimeType); // int
Location l3 = Location<String>('aaa', 'bbb');
print(l3.x.runtimeType); // String
}
}
class Location<T> {
T x;
T y;
Location(this.x, this.y);
}
也可以在类定义的时候限定类型?
main(List<String> args) {
Location l2 = Location<int>(10, 20);
print(l2.x.runtimeType);
// 错误的写法, 类型必须继承自num
Location l3 = Location<String>('aaa', 'bbb');
print(l3.x.runtimeType);
}
class Location<T extends num> {
T x;
T y;
Location(this.x, this.y);
}
?3.泛型方法
使用的时候不用指定类型直接传参
main(List<String> args) {
var names = ['why', 'kobe'];
var first = getFirst(names);//直接传参
print('$first ${first.runtimeType}'); // why String
}
T getFirst<T>(List<T> ts) {
return ts[0];
}
|