Funções
Tudo sobre funções em Dart.
Dart é uma linguagem verdadeiramente orientada a objetos, portanto até as funções são objetos e têm um tipo, Function.. Isso significa que funções podem ser atribuídas a variáveis ou passadas como argumentos para outras funções. Você também pode chamar uma instância de uma classe Dart como se fosse uma função. Para detalhes, veja Objetos chamáveis.
Aqui está um exemplo de implementação de uma função:
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
Embora o Effective Dart recomende anotações de tipo para APIs públicas, a função ainda funciona se você omitir os tipos:
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
Para funções que contêm apenas uma expressão, você pode usar uma sintaxe abreviada:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
A sintaxe => expr é uma abreviação para
{ return expr; }. A notação =>
às vezes é chamada de sintaxe arrow.
Parâmetros
#Uma função pode ter qualquer número de parâmetros posicionais obrigatórios. Eles podem ser seguidos por parâmetros nomeados ou por parâmetros posicionais opcionais (mas não por ambos).
Você pode usar vírgulas finais ao passar argumentos para uma função ou ao definir parâmetros de função.
Parâmetros nomeados
#
Parâmetros nomeados são opcionais,
a menos que estejam explicitamente marcados como required.
Ao definir uma função, use
{param1, param2, …}
para especificar parâmetros nomeados.
Se você não fornecer um valor padrão
nem marcar um parâmetro nomeado como required,
seus tipos devem ser anuláveis,
pois o valor padrão será null:
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool? bold, bool? hidden}) {
...
}
Ao chamar uma função,
você pode especificar argumentos nomeados usando
paramName: value.
Por exemplo:
enableFlags(bold: true, hidden: false);
Para definir um valor padrão para um parâmetro nomeado diferente de null,
use = para especificar um valor padrão.
O valor especificado deve ser uma constante em tempo de compilação.
Por exemplo:
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold = false, bool hidden = false}) {
...
}
// bold will be true; hidden will be false.
enableFlags(bold: true);
Se você preferir que um parâmetro nomeado seja obrigatório,
exigindo que quem chama forneça um valor para ele,
anote-o com required:
const Scrollbar({super.key, required Widget child});
Se alguém tentar criar um Scrollbar
sem especificar o argumento child,
o analisador reporta um problema.
Você pode querer colocar os argumentos posicionais primeiro, mas o Dart não exige isso. O Dart permite que argumentos nomeados sejam colocados em qualquer lugar da lista de argumentos quando isso se adequa à sua API:
repeat(times: 2, () {
...
});
Parâmetros posicionais opcionais
#
Envolver um conjunto de parâmetros de função em []
marca esses parâmetros como posicionais opcionais.
Se você não fornecer um valor padrão,
seus tipos devem ser anuláveis,
pois o valor padrão será null:
String say(String from, String msg, [String? device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
Aqui está um exemplo de chamada desta função sem o parâmetro opcional:
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
E aqui está um exemplo de chamada desta função com o terceiro parâmetro:
assert(
say('Bob', 'Howdy', 'smoke signal') ==
'Bob says Howdy with a smoke signal',
);
Para definir um valor padrão para um parâmetro posicional opcional diferente de null,
use = para especificar um valor padrão.
O valor especificado deve ser uma constante em tempo de compilação.
Por exemplo:
String say(String from, String msg, [String device = 'carrier pigeon']) {
var result = '$from says $msg with a $device';
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon');
Modificadores de parâmetro
#
Os modificadores de parâmetro final e var são reservados exclusivamente para
construtores primários, que os usam para declarar campos de instância.
Usá-los em parâmetros formais de qualquer outra declaração gera um
erro em tempo de compilação (extraneous_modifier).
Para exemplos de código e passos de migração, veja
Restrições de modificadores de parâmetro.
Para exigir que parâmetros não sejam reatribuídos, como escolha de estilo,
use a regra de lint parameter_assignments
no lugar.
A função main()
#
Toda aplicação deve ter uma função main() de nível superior, que serve como
ponto de entrada da aplicação. A função main() retorna void
e tem um
parâmetro opcional List<String> para argumentos.
Aqui está uma função main() simples:
void main() {
print('Hello, World!');
}
Aqui está um exemplo da função main() para uma aplicação de linha de comando que
recebe argumentos:
// Run the app like this: dart run args.dart 1 test
void main(List<String> arguments) {
print(arguments);
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
Você pode usar a biblioteca args para definir e analisar argumentos de linha de comando.
Funções como objetos de primeira classe
#Você pode passar uma função como parâmetro para outra função. Por exemplo:
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
Você também pode atribuir uma função a uma variável, como:
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
Este exemplo usa uma função anônima. Mais sobre elas na próxima seção.
Tipos de função
#
Você pode especificar o tipo de uma função, que é conhecido como tipo de função.
Um tipo de função é obtido de um cabeçalho de declaração de função
substituindo o nome da função pela keyword Function.
Além disso, você pode omitir os nomes dos parâmetros posicionais, mas
os nomes dos parâmetros nomeados não podem ser omitidos. Por exemplo:
void greet(String name, {String greeting = 'Hello'}) =>
print('$greeting $name!');
// Store `greet` in a variable and call it.
void Function(String, {String greeting}) g = greet;
g('Dash', greeting: 'Howdy');
Funções anônimas
#
Embora você dê nome à maioria das funções, como main() ou printElement(),
também pode criar funções sem nome.
Essas funções são chamadas de funções anônimas, lambdas ou closures.
Uma função anônima se assemelha a uma função nomeada, pois tem:
- Zero ou mais parâmetros, separados por vírgula
- Anotações de tipo opcionais entre parênteses.
O bloco de código a seguir contém o corpo da função:
([[Type] param1[, ...]]) {
codeBlock;
}
O exemplo a seguir passa uma função anônima
com um parâmetro sem tipo, item,
para a função map.
A função map, invocada para cada item da lista,
converte cada string para maiúsculas.
Depois, um laço for-in imprime cada string convertida com o seu comprimento.
const list = ['apples', 'bananas', 'oranges'];
var uppercaseList = list.map((item) {
return item.toUpperCase();
}).toList();
// Convert to list after mapping
for (var item in uppercaseList) {
print('$item: ${item.length}');
}
Clique em Run para executar o código.
void main() {
const list = ['apples', 'bananas', 'oranges'];
var uppercaseList = list.map((item) {
return item.toUpperCase();
}).toList();
// Convert to list after mapping
for (var item in uppercaseList) {
print('$item: ${item.length}');
}
}
Se a função contém apenas uma expressão ou instrução return, você pode encurtá-la usando a notação arrow. Cole a linha a seguir no DartPad e clique em Run para verificar que ela é funcionalmente equivalente.
var uppercaseList = list.map((item) => item.toUpperCase()).toList();
Escopo léxico
#O Dart determina o escopo das variáveis com base na estrutura do código. Uma linguagem de programação com esse recurso é chamada de linguagem com escopo léxico. Você pode "seguir as chaves para fora" para ver se uma variável está no escopo.
Exemplo: uma série de funções aninhadas, com variáveis em cada nível de escopo:
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
O método nestedFunction() pode usar variáveis de todos os níveis,
até o nível superior.
Closures léxicos
#Um objeto de função que pode acessar variáveis do seu escopo léxico quando a função está fora desse escopo é chamado de closure.
Funções podem capturar variáveis definidas em escopos ao redor. No
exemplo a seguir, makeAdder() captura a variável addBy. Para onde quer que a
função retornada vá, ela se lembra de addBy.
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(int addBy) {
return (int i) => addBy + i;
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
// Create a function that adds 4.
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
Tear-offs
#Quando você se refere a uma função, método ou construtor nomeado sem parênteses, o Dart cria um tear-off. Trata-se de um closure que recebe os mesmos parâmetros da função e invoca a função subjacente quando você a chama. Se o seu código precisa de um closure que invoque uma função nomeada com os mesmos parâmetros que o closure aceita, não envolva a chamada em um lambda. Use um tear-off.
var charCodes = [68, 97, 114, 116];
var buffer = StringBuffer();
// Function tear-off
charCodes.forEach(print);
// Method tear-off
charCodes.forEach(buffer.write);
// Function lambda
charCodes.forEach((code) {
print(code);
});
// Method lambda
charCodes.forEach((code) {
buffer.write(code);
});
Testando funções quanto à igualdade
#Aqui está um exemplo de teste de igualdade entre funções de nível superior, métodos estáticos e métodos de instância:
void foo() {} // A top-level function
class A {
static void bar() {} // A static method
void baz() {} // An instance method
}
void main() {
Function x;
// Comparing top-level functions.
x = foo;
assert(foo == x);
// Comparing static methods.
x = A.bar;
assert(A.bar == x);
// Comparing instance methods.
var v = A(); // Instance #1 of A
var w = A(); // Instance #2 of A
var y = w;
x = w.baz;
// These closures refer to the same instance (#2),
// so they're equal.
assert(y.baz == x);
// These closures refer to different instances,
// so they're unequal.
assert(v.baz != w.baz);
}
Valores de retorno
#
Todas as funções retornam um valor. Se nenhum valor de retorno for especificado, a
instrução return null; é implicitamente anexada ao corpo da função.
foo() {}
assert(foo() == null);
Para retornar múltiplos valores de uma função, agregue-os em um record.
(String, int) foo() {
return ('something', 42);
}
Getters e setters
#Todo acesso a propriedade (de nível superior, estática ou de instância) é uma invocação de um getter ou de um setter. Uma variável cria implicitamente um getter e, se for mutável, um setter. É por isso que, ao acessar uma propriedade, você está na verdade chamando uma pequena função por trás dos panos. Ler uma propriedade chama uma função getter, e escrever nela chama uma função setter, mesmo nos casos em que a propriedade é declarada como variável.
No entanto, você também pode declarar getters e setters explicitamente com
as keywords get e set, respectivamente.
Isso permite que o valor de uma propriedade seja calculado quando é lido ou escrito.
O propósito de usar getters e setters é criar uma separação clara entre o cliente (o código que usa a propriedade) e o provedor (a classe ou biblioteca que a define). O cliente pede ou define um valor sem precisar saber se esse valor está armazenado em uma variável simples ou calculado na hora. Isso dá ao provedor a liberdade de mudar como a propriedade funciona.
Por exemplo, como o valor da propriedade pode não estar armazenado em lugar nenhum, ele pode ser calculado toda vez que o getter é chamado. Outro exemplo é quando um valor é armazenado em uma variável privada e o acesso público é permitido apenas por meio de um getter ou de um setter.
O exemplo a seguir mostra isso,
com o getter e o setter secret dando
acesso indireto à variável privada _secret, com
suas próprias manipulações dos valores atribuídos e recuperados.
// Defines a variable `_secret` that is private to the library since
// its identifier starts with an underscore (`_`).
String _secret = 'Hello';
// A public top-level getter that
// provides read access to [_secret].
String get secret {
print('Getter was used!');
return _secret.toUpperCase();
}
// A public top-level setter that
// provides write access to [_secret].
set secret(String newMessage) {
print('Setter was used!');
if (newMessage.isNotEmpty) {
_secret = newMessage;
print('New secret: "$newMessage"');
}
}
void main() {
// Reading the value calls the getter.
print('Current message: $secret');
/*
Output:
Getter was used!
Current message: HELLO
*/
// Assigning a value calls the setter.
secret = 'Dart is fun';
// Reading it again calls the getter to show the new computed value
print('New message: $secret');
/*
Output:
Setter was used! New secret: "Dart is fun"
Getter was used!
New message: DART IS FUN
*/
}
Geradores
#Quando você precisa produzir uma sequência de valores de forma preguiçosa (lazy), considere usar uma função geradora. O Dart tem suporte nativo para dois tipos de funções geradoras:
Para implementar uma função geradora síncrona,
marque o corpo da função como sync*
e use instruções yield para entregar os valores:
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
Para implementar uma função geradora assíncrona,
marque o corpo da função como async*
e use instruções yield para entregar os valores:
Stream<int> asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
Se o seu gerador é recursivo,
você pode melhorar o desempenho usando yield*:
Iterable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
Funções externas
#
Uma função externa é uma função cujo corpo é implementado separadamente da
sua declaração. Inclua a keyword external antes de uma declaração de função, assim:
external void someFunc(int i);
A implementação de uma função externa pode vir de outra biblioteca Dart
ou, mais comumente, de outra linguagem. Em contextos de interoperabilidade, external
introduz informações de tipo para funções ou valores estrangeiros,
tornando-os utilizáveis em Dart. A implementação e o uso são
altamente específicos da plataforma, então consulte a documentação de interoperabilidade sobre, por exemplo,
C ou JavaScript
para saber mais.
Funções externas podem ser funções de nível superior, métodos de instância,
getters ou setters, ou construtores não redirecionados.
Uma variável de instância também pode ser
external,
o que equivale a um getter externo e (se a variável
não for final) a um setter externo.
Salvo indicação em contrário, a documentação neste site reflete Dart 3.13.7. Página atualizada pela última vez em 2026-11-12. Ver código-fonte ou relatar um problema.
Encontrou essa página sem tradução ou que precisa de correção? Abra uma issue e nos ajude a manter esse site em PT-BR para ajudar pessoas como você.