part e part of | Library | Dart | Flutter
partepart of| Library | Dart | Flutter
No Dart, uma library é a unidade de organização, encapsulamento e privacidade do código. Oficialmente, cada arquivo Dart — junto com seus parts, se existirem — forma uma library. Identificadores que começam com _ ficam visíveis somente dentro dessa library.
No Dart, part e part of servem para dividir uma mesma library em múltiplos arquivos. Eles não funcionam como import e também não equivalem a partial class do C#. O objetivo é separar um arquivo grande em pedaços menores, mantendo tudo dentro da mesma unidade lógica de library.
Conceito principal
Quando você usa part, os arquivos envolvidos passam a fazer parte da mesma library.
Com isso, membros com _ continuam acessíveis entre esses arquivos, porque em Dart o _ indica privacidade no nível de library, não no nível de arquivo.
Como funciona
Você tem um arquivo principal:
library user_page;
import 'package:flutter/material.dart';
part 'user_page_view.dart';
part 'user_page_logic.dart';
class UserPage extends StatefulWidget {
const UserPage({super.key});
State<UserPage> createState() => _UserPageState();
}
class _UserPageState extends State<UserPage> {
int _counter = 0;
void _increment() {
setState(() => _counter++);
}
Widget build(BuildContext context) {
return buildScaffold();
}
}
E os arquivos complementares:
part of 'user_page.dart';
extension _UserPageView on _UserPageState {
Widget buildScaffold() {
return Scaffold(
appBar: AppBar(title: const Text('Usuário')),
body: Center(
child: Text('$_counter'),
),
floatingActionButton: FloatingActionButton(
onPressed: _increment,
child: const Icon(Icons.add),
),
);
}
}
part of 'user_page.dart';
extension _UserPageLogic on _UserPageState {
void carregarDados() {
_counter = 10;
}
}
O que cada palavra-chave faz
part
Declara, no arquivo principal, que outro arquivo pertence à mesma library.
Exemplo:
part 'user_page_view.dart';
part 'user_page_logic.dart';
Isso diz ao compilador que esses arquivos não são libraries independentes; eles são fragmentos da library principal.
part of
Declara, no arquivo secundário, a qual library ele pertence.
Exemplo:
part of 'user_page.dart';
Esse arquivo não deve ser tratado isoladamente. Ele existe como parte da library definida no arquivo principal.
Regras importantes
1. Arquivo com part of não usa import para acessar o principal
Ele não importa o arquivo principal. Ele pertence à mesma library, então o acesso ocorre por compartilhamento da library, não por importação.
2. O import fica no arquivo principal
Na prática, normalmente você centraliza import, export e definição da library no arquivo principal, e os arquivos part ficam s ó com o código complementar. Isso segue a forma como Dart organiza libraries.
3. Privado com _ continua funcionando entre os arquivos
Como a privacidade é por library, isto funciona:
class _UserPageState extends State<UserPage> {
int _counter = 0;
}
E em outro arquivo part:
part of 'user_page.dart';
extension _UserPageLogic on _UserPageState {
void testar() {
_counter++;
}
}
Isso é permitido porque ambos pertencem à mesma library.
4. part não substitui arquitetura
part ajuda a organizar arquivo grande, mas não separa responsabilidade de verdade.
Se a tela está grande porque mistura UI, regra de negócio, acesso a dados e estado, o ideal costuma ser extrair widgets, controllers, services, cubits, blocs ou notifiers. Isso é consistente com a forma como Dart recomenda estruturar bibliotecas e APIs de forma mantível. (Dart)
Quando usar
part faz sentido quando:
- a tela ficou grande demais;
- você quer dividir UI, ações e helpers sem perder acesso aos membros privados;
- tudo ainda pertence claramente à mesma unidade de código.
Exemplo comum em Flutter:
produto_page.dartproduto_page_view.dartproduto_page_actions.dartproduto_page_state.dart
Quando evitar
Evite part quando:
- o código já representa responsabilidades diferentes;
- você quer reutilizar aquele trecho em outras telas;
- você quer isolamento mais claro entre camadas;
- o arquivo secundário deveria ser uma library própria.
Nesses casos, prefira arquivos separados com import, ou componentes específicos da arquitetura da app.
Diferença entre part e import
import
Usado para consumir outra library.
import 'package:flutter/material.dart';
Aqui você está usando código externo à sua library.
part
Usado para incluir outro arquivo na mesma library.
part 'user_page_view.dart';
Aqui você está apenas quebrando a implementação da mesma library em vários arquivos.
Diferença entre part e export
export
Serve para reexpor outra library como parte da API pública.
export 'src/meu_widget.dart';
Isso é útil para organizar API pública de pacote ou módulo. (Dart)
part
Não reexpõe nada. Só divide internamente a mesma library.
Exemplo prático para Flutter
Arquivo principal
library login_page;
import 'package:flutter/material.dart';
part 'login_page_view.dart';
part 'login_page_form.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
bool _loading = false;
void _submit() {
setState(() => _loading = true);
}
Widget build(BuildContext context) {
return buildView(context);
}
}
Parte da view
part of 'login_page.dart';
extension _LoginPageView on _LoginPageState {
Widget buildView(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Login')),
body: Padding(
padding: const EdgeInsets.all(16),
child: buildForm(),
),
);
}
}
Parte do formulário
part of 'login_page.dart';
extension _LoginPageForm on _LoginPageState {
Widget buildForm() {
return Column(
children: [
TextField(controller: _emailController),
TextField(controller: _passwordController),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _loading ? null : _submit,
child: const Text('Entrar'),
),
],
);
}
}
Vantagens
- reduz o tamanho visual do arquivo principal;
- mantém acesso a membros privados;
- facilita separar blocos grandes de UI;
- útil para telas StatefulWidget muito extensas.
Desvantagens
- pode esconder acoplamento excessivo;
- dificulta navegação se usado em excesso;
- arquivos
partnão são independentes; - não favorece reutilização como libraries separadas.
Boas práticas
Use part para organização local
Bom para separar:
- builders de UI;
- extensões internas;
- helpers específicos da tela;
- trechos grandes de implementação.
Não use part para tudo
Se um arquivo pode viver sozinho, provavelmente ele deveria ser uma library própria com import.
Prefira nomes claros
Exemplos:
pedido_page.dartpedido_page_view.dartpedido_page_actions.dartpedido_page_helpers.dart
Evite espalhar demais
Se uma tela tem 8 ou 10 arquivos part, normalmente já passou do ponto.
Nesse caso, a classe provavelmente precisa ser redesenhada.
Erros comuns
Esquecer o part no arquivo principal
part 'user_page_view.dart';
Sem isso, o arquivo secundário não será incluído na library.
Esquecer o part of no arquivo secundário
part of 'user_page.dart';
Sem isso, o arquivo não pertence à library principal.
Tentar usar part como se fosse import
part não serve para compartilhar código entre módulos independentes.
Para isso, use libraries separadas com import e, quando fizer sentido, export.
Resumo direto
partdivide uma mesma library em vários arquivos.part ofconecta o arquivo secundário à library principal._em Dart é privado por library.partajuda na organização.partnão substitui separação arquitetural.
Regra prática para o seu caso
Se sua tela está grande, você pode usar part para separar:
- layout;
- ações;
- helpers;
- trechos de estado.
Mas, se ela está grande porque concentra responsabilidades demais, o melhor caminho é extrair widgets e lógica para classes próprias.