Skip to main content

Imports e Exports no Dart | Dart

  • Imports e Exports no Dart | Dart

O sistema de módulos do Dart é baseado em bibliotecas (libraries). Cada arquivo .dart é, por padrão, uma biblioteca. O controle de visibilidade, encapsulamento e composição de APIs ocorre por meio de:

  • import
  • export
  • library
  • part / part of

Este documento cobre todas as variações e combinações relevantes desses mecanismos.


1. import

Permite utilizar símbolos (classes, funções, variáveis, extensões, enums) definidos em outra biblioteca.

1.1 Import básico

import 'package:meu_app/utils/logger.dart';

Ou arquivo relativo:

import '../utils/logger.dart';

Ou biblioteca do SDK:

import 'dart:math';
import 'dart:convert';

1.2 Import com prefixo (as)

Evita colisão de nomes.

import 'dart:math' as math;

void main() {
print(math.pi);
}

Use quando:

  • Há conflito de nomes
  • Deseja deixar explícita a origem do símbolo

1.3 Import seletivo (show)

Importa apenas símbolos específicos.

import 'dart:math' show pi, Random;

Reduz superfície de exposição e melhora legibilidade.


1.4 Import com exclusão (hide)

Importa tudo, exceto símbolos específicos.

import 'dart:math' hide Random;

Útil quando há colisão de nomes.


1.5 Import condicional

Muito utilizado em Flutter Web / Mobile.

import 'src/io_stub.dart'
if (dart.library.io) 'src/io_impl.dart'
if (dart.library.html) 'src/web_impl.dart';

Baseado em environment libraries.

Principais condições:

  • dart.library.io
  • dart.library.html
  • dart.library.js
  • dart.library.ffi

1.6 Deferred Import (Lazy Loading)

Carrega biblioteca sob demanda.

import 'package:meu_app/feature.dart' deferred as feature;

Future<void> loadFeature() async {
await feature.loadLibrary();
feature.run();
}

Restrições:

  • Funciona principalmente no Flutter Web
  • Não suporta dart:mirrors
  • Necessita chamada explícita loadLibrary()

2. export

Reexpõe símbolos de outra biblioteca.

Muito usado para criar barrel files.


2.1 Export simples

export 'src/models/user.dart';
export 'src/models/order.dart';

Arquivo models.dart:

export 'src/models/user.dart';
export 'src/models/order.dart';

Uso:

import 'package:meu_app/models.dart';

2.2 Export com show

export 'src/internal.dart' show PublicClass;

2.3 Export com hide

export 'src/internal.dart' hide InternalHelper;

2.4 Reexport encadeado

// a.dart
export 'b.dart';

// b.dart
export 'c.dart';

Ao importar a.dart, você obtém símbolos de c.dart.


3. library

Define explicitamente o nome da biblioteca.

library meu_app.utils;

Hoje é opcional na maioria dos casos. Útil principalmente com part.


4. part e part of

Permite dividir uma única biblioteca em múltiplos arquivos.

4.1 Arquivo principal

library user_module;

part 'user_model.dart';
part 'user_repository.dart';

4.2 Arquivo part

part of user_module;

class User {
final String name;
User(this.name);
}

Características importantes:

  • Compartilham o mesmo namespace
  • Membros privados (_private) são acessíveis entre parts
  • Não é um import real
  • Não gera biblioteca separada

5. Visibilidade e Encapsulamento

Dart usa privacidade por biblioteca, não por classe.

Símbolos iniciados com _ são privados à biblioteca.

class _InternalClass {}

Se você dividir código com part, o privado continua acessível.

Se usar import, o privado não é acessível.


6. Importando dart: Libraries

Principais bibliotecas nativas:

  • dart:core (import automático)
  • dart:async
  • dart:convert
  • dart:collection
  • dart:math
  • dart:io
  • dart:ffi
  • dart:isolate
  • dart:html

Exemplo:

import 'dart:async';
import 'dart:isolate';

7. Importando pacotes (package:)

import 'package:http/http.dart';

Baseado no pubspec.yaml.

O Dart resolve via:

  • .dart_tool/package_config.json

8. Barrel Pattern (Arquitetura)

Estrutura recomendada:

lib/
├── src/
│ ├── service.dart
│ ├── repository.dart

└── feature.dart

feature.dart:

export 'src/service.dart';
export 'src/repository.dart';

Benefícios:

  • API pública controlada
  • Evita expor src/
  • Permite refatorar internamente sem quebrar consumidores

9. Resolução de Conflitos

Caso 1 – Mesmo nome

import 'a.dart';
import 'b.dart'; // ambos possuem class User

Erro: Ambiguous reference.

Solução:

import 'a.dart' as a;
import 'b.dart' as b;

a.User userA;
b.User userB;

Caso 2 – show + prefix

import 'a.dart' as a show User;

10. Best Practices

10.1 Use package: em vez de relativo para código público

Preferível:

import 'package:meu_app/utils.dart';

Evita problemas com reorganização de pastas.


10.2 Não exponha src/

Estrutura ideal:

lib/
├── src/ (privado)
└── meu_app.dart (API pública)

10.3 Evite uso excessivo de part

Use part apenas quando:

  • Geradores de código (ex: json_serializable, freezed)
  • Código altamente coeso

Evite para organização comum — prefira import.


11. Import em testes

Em testes:

import 'package:meu_app/src/internal.dart';

É permitido, mas viola encapsulamento lógico. Faça apenas quando necessário.


12. Imports implícitos

O Dart automaticamente importa:

import 'dart:core';

Sempre disponível:

  • String
  • int
  • List
  • Map
  • Future
  • etc.

13. Imports e Null Safety

Não há impacto direto no sistema de import/export. A null safety é analisada no nível de biblioteca durante compilação.


14. Casos Avançados

14.1 Import + extensão

import 'string_extensions.dart';

void main() {
print("hello".capitalize());
}

14.2 Import cíclico

// a.dart
import 'b.dart';

// b.dart
import 'a.dart';

Evite. Pode gerar inconsistências e acoplamento excessivo.

Solução:

  • Extraia interfaces
  • Crie camada intermediária

15. Fluxo de Resolução do Compilador

Ordem lógica:

  1. Resolve imports
  2. Aplica show/hide
  3. Mescla namespace
  4. Detecta conflitos
  5. Aplica prefixos
  6. Resolve exports transitivos

16. Resumo Técnico

RecursoFinalidade
importConsumir outra biblioteca
asCriar namespace
showImportar seletivamente
hideExcluir símbolos
deferredLazy loading
exportReexpor API
libraryNomear biblioteca
partDividir mesma biblioteca