---
title: "@hasDecl em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/builtins/@hasdecl-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/builtins/@hasdecl-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa do @hasDecl em Zig. Verifique se um tipo possui uma declaração (função, constante) em tempo de compilação. Exemplos práticos pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# @hasDecl em Zig — Referência e Exemplos

Referência completa do @hasDecl em Zig. Verifique se um tipo possui uma declaração (função, constante) em tempo de compilação. Exemplos práticos pt-BR.


# @hasDecl em Zig

O `@hasDecl` verifica em tempo de compilação se um tipo (geralmente um struct, enum ou union) possui uma declaração específica — seja uma função, constante ou tipo aninhado. Retorna `true` ou `false`, permitindo código genérico que se adapta às capacidades do tipo recebido.

## Sintaxe

```zig
@hasDecl(comptime T: type, comptime name: []const u8) bool
```

## Parâmetros

- **T** (`type`, comptime): O tipo a ser inspecionado.
- **name** (`[]const u8`, comptime): O nome da declaração a verificar, como string.

## Valor de retorno

Retorna `bool` — `true` se o tipo `T` possui uma declaração pública com o nome especificado, `false` caso contrário.

## Exemplos práticos

### Exemplo 1: Verificar se tipo tem método

```zig
const std = @import("std");

const Animal = struct {
    nome: []const u8,

    pub fn falar(self: Animal) []const u8 {
        _ = self;
        return "...";
    }
};

const Pedra = struct {
    peso: f64,
};

fn descrever(valor: anytype) void {
    const T = @TypeOf(valor);
    if (@hasDecl(T, "falar")) {
        std.debug.print("Fala: {s}\n", .{valor.falar()});
    } else {
        std.debug.print("(sem fala)\n", .{});
    }
}

pub fn main() void {
    const gato = Animal{ .nome = "Gato" };
    const pedra = Pedra{ .peso = 2.5 };

    descrever(gato);  // Fala: ...
    descrever(pedra);  // (sem fala)
}
```

### Exemplo 2: Interface opcional com fallback

```zig
const std = @import("std");

fn formatar(valor: anytype) []const u8 {
    const T = @TypeOf(valor);
    if (@hasDecl(T, "formato")) {
        return T.formato;
    } else {
        return @typeName(T);
    }
}

const Celsius = struct {
    pub const formato = "°C";
    graus: f64,
};

const Ponto = struct {
    x: f64,
    y: f64,
};

pub fn main() void {
    const temp = Celsius{ .graus = 25.0 };
    const ponto = Ponto{ .x = 1, .y = 2 };

    std.debug.print("{s}\n", .{formatar(temp)});   // °C
    std.debug.print("{s}\n", .{formatar(ponto)});   // Ponto
}
```

### Exemplo 3: Verificar presença de deinit

```zig
const std = @import("std");

fn limpar(valor: anytype) void {
    const T = @TypeOf(value);
    const info = @typeInfo(T);
    if (info == .pointer) {
        const Child = info.pointer.child;
        if (@hasDecl(Child, "deinit")) {
            valor.deinit();
        }
    }
}
```

## Casos de uso comuns

1. **Interfaces opcionais**: Verificar se um tipo implementa métodos específicos antes de chamá-los.
2. **Código genérico adaptativo**: Funções que se comportam diferente dependendo das capacidades do tipo.
3. **Frameworks e bibliotecas**: Detectar hooks e callbacks opcionais definidos pelo usuário.
4. **Validação em comptime**: Gerar `@compileError` se um tipo obrigatório não possuir uma declaração esperada.

## Diferença entre `@hasDecl` e `@hasField`

É importante não confundir esses dois builtins:

- **`@hasField`** verifica a existência de **campos de dados** (membros que armazenam valores em instâncias da struct).
- **`@hasDecl`** verifica a existência de **declarações** — funções, constantes, tipos aninhados e variáveis definidas no namespace do tipo.

```zig
const Exemplo = struct {
    campo_de_dados: u32,        // campo — verificado com @hasField

    pub const CONSTANTE = 42;   // declaração — verificada com @hasDecl
    pub fn metodo(self: @This()) void { _ = self; } // declaração
};

// @hasField verifica campos de instância
_ = @hasField(Exemplo, "campo_de_dados"); // true
_ = @hasField(Exemplo, "CONSTANTE");      // false — CONSTANTE não é campo

// @hasDecl verifica declarações do namespace
_ = @hasDecl(Exemplo, "CONSTANTE");      // true
_ = @hasDecl(Exemplo, "metodo");         // true
_ = @hasDecl(Exemplo, "campo_de_dados"); // false — campo não é declaração
```

## Padrão de interfaces em Zig com `@hasDecl`

Zig não tem interfaces formais, mas `@hasDecl` permite implementar um padrão similar de forma segura:

```zig
fn assertImplementaWriter(comptime T: type) void {
    if (!@hasDecl(T, "write")) {
        @compileError(@typeName(T) ++ " deve implementar o método 'write'");
    }
    if (!@hasDecl(T, "flush")) {
        @compileError(@typeName(T) ++ " deve implementar o método 'flush'");
    }
}

fn escreverComBuffer(comptime W: type, writer: W, dados: []const u8) !void {
    comptime assertImplementaWriter(W);
    // ... uso seguro de writer.write e writer.flush
    try writer.write(dados);
    try writer.flush();
}
```

Esse padrão garante erros de compilação claros quando um tipo não satisfaz os requisitos, em vez de erros obscuros sobre métodos não encontrados.

## Considerações de desempenho

`@hasDecl` é avaliado exclusivamente em tempo de compilação e não tem nenhum custo em runtime. Blocos `if (@hasDecl(...))` são equivalentes a `comptime if`, e o compilador gera apenas o código do ramo que será executado, eliminando dead code completamente.

## Perguntas Frequentes

**P: `@hasDecl` verifica declarações privadas (sem `pub`)?**

Não para tipos externos. `@hasDecl` respeita a visibilidade: só retorna `true` para declarações que são acessíveis no contexto onde a verificação ocorre. Declarações `pub` são sempre verificáveis; declarações sem `pub` só são visíveis dentro do mesmo arquivo.

**P: É possível verificar se um tipo tem uma declaração de um tipo específico (não apenas pelo nome)?**

`@hasDecl` verifica apenas a existência pelo nome. Para verificar o tipo da declaração, use `@hasDecl` para confirmar a existência e depois `@TypeOf(@field(T, "nome"))` para obter o tipo da declaração e validá-lo com `comptime`.

**P: `@hasDecl` funciona com módulos importados (resultado de `@import`)?**

Sim. O resultado de `@import` é um tipo (a struct de nível superior do módulo), e `@hasDecl` pode verificar qualquer declaração pública nesse módulo.

## Builtins relacionados

- [@hasField](/builtins/has-field/) — Verifica se um tipo possui um campo (não declaração)
- [@typeInfo](/builtins/type-info/) — Informações detalhadas sobre um tipo
- [@typeName](/builtins/type-name/) — Nome de um tipo como string
- [@field](/builtins/field/) — Acessa campo por nome em comptime

## Tutoriais relacionados

- [Comptime em Zig — Guia Completo](/tutoriais/comptime-em-zig/)
- [Zig Comptime e Reflection](/tutoriais/zig-comptime-reflection/)
- [Zig Design Patterns](/tutoriais/zig-design-patterns/)
