Dart语言的一些基本特性:类型和使用参数

91 阅读5分钟

本教程介绍了Dart语言的一些基本特性,并展示了如何在实践中使用它们。

正确使用它们,可以使代码清晰轻量、更健壮

1.类型推断

Dart编译器可以从变量的初始化器中自动推断出变量的类型,这样我们就不必自己声明类型了。

在实践中,这意味着我们可以将这段代码。

String name = 'Andrea';
int age = 35;
double height = 1.84;

到这个。

var name = 'Andrea';
var age = 35;
var height = 1.84;

这样做是因为Dart可以从赋值右边的表达式中推断出类型。


我们可以像这样声明一个变量。

var x;
x = 15;
x = 'hello';

在这种情况下,x先声明后初始化

它的类型是dynamic ,意味着它可以从不同类型的表达式中被赋值。

经验之谈

  • 在使用var ,只要变量是同时声明初始化的,Dart会推断出正确的类型。

2.final和const

当一个变量用var声明后,它可以被再次赋值。

var name = 'Andrea';
name = 'Bob';

换句话说。

var 意味着多次赋值

这在final 中是不允许的。

final name = 'Andrea';
name = 'Bob'; // 'name', a final variable, can only be set once

Final在实践中

在widget类内部声明属性时,使用final 是非常常见的。例子。

class PlaceholderContent extends StatelessWidget {
  const PlaceholderContent({
    this.title,
    this.message,
  });
  final String title;
  final String message;
  
  // TODO: Implement build method
}

这里,titlemessage 不能在widget里面被修改,因为。

final 意味着单一赋值

所以,varfinal 之间的区别是关于多重赋值与单一赋值。现在让我们看一下const

const

const 定义了一个编译时常量。

const 用于定义硬编码的值,如颜色、字体大小和图标。

但我们也可以在定义widget类时使用constructor

这是有可能的,只要小组件内部的一切也是一个编译时常量。例子。

class PlaceholderContent extends StatelessWidget {
  const PlaceholderContent({
    this.title,
    this.message,
  });
  final String title;
  final String message;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            title,
            style: TextStyle(fontSize: 32.0, color: Colors.black54),
          ),
          Text(
            message,
            style: TextStyle(fontSize: 16.0, color: Colors.black54),
          ),
        ],
      ),
    );
  }
}

而如果一个widget有一个const 构造函数,它就可以像这样构建。

const PlaceholderContent(
  title: 'Nothing here',
  message: 'Add a new item to get started',
)

因此,这个widget被Flutter优化了,因为当父类改变时,它不会被重新构建

经验之谈。

3.命名参数和位置参数

在Dart中,我们用大括号({})来定义命名参数。

class PlaceholderContent extends StatelessWidget {
  // constructor with named parameters
  const PlaceholderContent({
    this.title,
    this.message,
  });
  final String title;
  final String message;
  
  // TODO: Implement build method
}

这意味着我们可以像这样创建上面的小部件。

PlaceholderContent(
  title: 'Nothing here',
  message: 'Add a new item to get started',
)

作为一种选择,我们可以在构造函数中省略大括号来声明位置参数。

// constructor with positional parameters
const PlaceholderContent(
  this.title,
  this.message,
);

结果,参数是由它们的位置定义的。

PlaceholderContent(
  'Nothing here', // title at position 0
  'Add a new item to get started', // message at position 1
)

这很有效,但当我们有很多参数时,很快就会变得混乱。

命名的参数有助于解决这个问题,因为它们使代码更容易编写(和阅读)。


顺便说一下,你可以像这样结合位置参数和命名参数。

// positional parameters first, then named parameters
void _showAlert(BuildContext context, {String title, String content}) {
  // TODO: Show Alert
}

Flutter小组件通常有一个单一的位置参数,然后是命名参数。Text widget就是一个很好的例子。

作为一个准则,我总是希望我的代码是清晰和不言自明的。而我也相应地选择使用命名参数或位置参数。

4.@required & default values

默认情况下,命名参数可以被省略。

省略一个命名的参数就等于给它一个null

而有时,这将导致意想不到的后果。

在上面的例子中,我们可以定义一个PlaceholderContent() ,而忘记传入titlemessage

而这将导致一个红色屏幕的错误,因为我们将把null 的数据值传递给Text 小工具,这是不允许的。

非空字符串错误


@required来拯救

我们可以像这样注解任何需要的参数。

const PlaceholderContent({
  @required this.title,
  @required this.message,
});

如果我们忘记传入这些参数,编译器会发出警告。

必需参数警告

尽管如此,如果我们想的话,我们可以明确地传递null 值。

PlaceholderContent(
  title: null,
  message: null,
)

编译器对此也很满意。

为了防止传递null 值,我们可以添加一些断言。

const PlaceholderContent({
  @required this.title,
  @required this.message,
}) : assert(title != null && message != null);

我们的代码在这种改变下会更安全,因为。

  • @required 增加了一个编译时检查
  • assert 增加了一个运行时检查

如果我们在代码中加入断言,那么运行时错误就更容易解决了,因为它们会准确地指向导致错误的那一行。

不可归零的类型

@required 和 ,使我们的代码更安全,但它们感觉有点笨拙。assert

如果我们能在编译时指定一个对象不能为空,那就更好了。

这一点可以通过非空洞类型来实现,这些类型从一开始就被内置于Swift和Kotlin。

而非空类型目前正在Dart语言中实现。

因此,我们可以掰着手指头希望它们尽快到来。🤞

默认值

有时,指定一些合理的默认值是很有用的。

这在Dart中是很容易的。

const PlaceholderContent({
  this.title = 'Nothing here',
  this.message = 'Add a new item to get started',
}) : assert(title != null && message != null);

通过这种语法,如果省略了titlemessage ,那么就会使用默认值。

顺便说一下,默认值也可以用位置参数来指定。

int sum([int a = 0, int b = 0]) {
  return a + b;
}
print(sum(10)); // prints 10

总结

代码是写给机器执行的,也是写给其他人类阅读的。

生命是短暂的。善待自己,写好代码 😉

  • 它使你的应用程序更健壮,更有性能。
  • 它可以帮助队友和你未来的自己。

编码愉快!