Swift: Definição de Funções e Parâmetros do Swift

As funções são os blocos fundamentais de construção de código no Swift. Esta lição ensina como definir funções e usar cada forma de parâmetro com flexibilidade, tornando seu código mais semântico e reutilizável.

1. O Que Você Vai Aprender


2. Uma História Real de um Engenheiro Back-End

(1) Problema: Significado pouco claro dos parâmetros no local da chamada

Bob está desenvolvendo um sistema de pedidos de e-commerce. Ele escreveu uma função para calcular o preço total do pedido:

SWIFT
func calculate(price: Double, count: Int, rate: Double) -> Double {
    return price * Double(count) * (1 - rate)
}
// At the call site — parameter meaning is guesswork
let result = calculate(price: 100, count: 3, rate: 0.1)

A equipe se dividiu sobre o que taxa: 0.1 significava — alguns achavam que era um imposto de 10%, outros achavam que era um desconto de 10%. A assinatura da função não expressava o papel semântico de cada parâmetro.

(2) A Solução com Rótulos de Argumento

O Swift permite definir tanto um rótulo externo quanto um nome interno para cada parâmetro, fazendo o local da chamada parecer linguagem natural:

SWIFT
func calculate(price: Double, count: Int, discount rate: Double) -> Double {
    return price * Double(count) * (1 - rate)
}
// Call site is clear: "discount" tells you it's a discount rate
let result = calculate(price: 100, count: 3, discount: 0.1)

(3) Resultado: Chamadas de função semanticamente claras

Dimensão Antes Depois
Significado do parâmetro Pura adivinhação Compreensível no local da chamada
Legibilidade do código Precisa pular para a definição Significado claro em uma linha
Comunicação da equipe Debates frequentes sobre significado Assinatura da função autodocumentada
Eficiência de manutenção Busca global ao alterar parâmetros Mudanças locais, sem ambiguidade

3. Definição Básica de Função

Uma função é um bloco de código reutilizável no Swift, definido com a palavra-chave func.

100%
graph LR
    A[palavra-chave func] --> B[Nome da função]
    B --> C[Lista de parâmetros]
    C --> D[Seta de retorno e tipo]
    D --> E[Corpo da função]
    A --> F["func saudacao(nome: String) -> String { return \"Olá \\(nome)\" }"]
Componente Obrigatório Observações
Palavra-chave func Sim Marca uma declaração de função
Nome da função Sim Identifica a função, use camelCase
Lista de parâmetros () Sim Parênteses vazios mesmo sem parâmetros
Retorno -> Tipo Não Omita para retornar Void
Corpo {} Sim O bloco de código executado pela função

(1) Sem Parâmetros, Sem Valor de Retorno

SWIFT
func sayHello() {
    print("Hello!")
}
sayHello() // Call

Saída:

TEXT 📖 Somente leitura
Hello!

(2) Parâmetros e Valores de Retorno

SWIFT
func add(a: Int, b: Int) -> Int {
    return a + b
}
let sum = add(a: 5, b: 3)
print("5 + 3 = \(sum)")

Saída:

TEXT 📖 Somente leitura
5 + 3 = 8

▶ Exemplo: Cálculo do Valor do Pedido

SWIFT
// ============================================
// Calculate order total including tax
// ============================================
func orderAmount(price: Double, quantity: Int) -> Double {
    return price * Double(quantity)
}
let amount = orderAmount(price: 29.99, quantity: 3)
print("Order amount: $\(amount)")

Saída:

TEXT 📖 Somente leitura
Order amount: $89.97

4. Rótulos de Argumento e Valores Padrão

(1) Rótulos de Argumento

O Swift permite especificar um rótulo externo (usado no local da chamada) e um nome interno (usado dentro do corpo da função) para cada parâmetro:

Estilo Sintaxe Local da Chamada Quando Usar
Rótulo = nome func foo(nome: String) foo(nome: ...) O nome do parâmetro é suficientemente semântico
Rótulo externo func foo(com nome: String) foo(com: ...) A chamada parece linguagem natural
Omitir rótulo func foo(_ nome: String) foo(...) O verbo já expressa o parâmetro
Combinações Rótulos variados Flexível Requisitos personalizados

▶ Exemplo: Comparando Estilos de Rótulo

SWIFT
// ============================================
// Three argument label styles compared
// ============================================
// 1. Default — label equals name
func greet1(name: String) {
    print("Hello, \(name)")
}
// 2. Custom external label
func greet2(to name: String) {
    print("Hello, \(name)")
}
// 3. Omit external label (underscore)
func greet3(_ name: String) {
    print("Hello, \(name)")
}
greet1(name: "Alice")
greet2(to: "Bob")
greet3("Charlie")

Saída:

TEXT 📖 Somente leitura
Hello, Alice
Hello, Bob
Hello, Charlie

(2) Valores Padrão de Parâmetro

Quando você fornece um valor padrão para um parâmetro, os chamadores podem omitir esse argumento:

SWIFT
func makeCoffee(size: String, sugar: Int = 1) -> String {
    return "\(size) coffee with \(sugar) sugar(s)"
}
print(makeCoffee(size: "Large"))           // Uses default sugar
print(makeCoffee(size: "Medium", sugar: 0)) // Custom sugar

Saída:

TEXT 📖 Somente leitura
Large coffee with 1 sugar(s)
Medium coffee with 0 sugar(s)

💡 Dica: Coloque os parâmetros padrão no final da lista de parâmetros para evitar ambiguidade nos locais de chamada.


5. Parâmetros Variádicos e inout

(1) Parâmetros Variádicos

Um parâmetro variádico aceita zero ou mais valores de um determinado tipo e fica disponível como um array dentro do corpo da função:

SWIFT
func sum(_ numbers: Double...) -> Double {
    var total = 0.0
    for number in numbers {
        total += number
    }
    return total
}
print(sum(1, 2, 3))       // 3 arguments
print(sum(10, 20))         // 2 arguments
print(sum())               // 0 arguments

Saída:

TEXT 📖 Somente leitura
6.0
30.0
0.0
Característica Descrição
Sintaxe Adicione ... após o tipo
Quantidade 0 a qualquer número
Tipo Todos os valores devem ser do mesmo tipo
Posição No máximo um por função; deve ser o último parâmetro

(2) Parâmetros inout

Um parâmetro inout permite que uma função modifique a variável do chamador — essencialmente passagem por referência em vez de por cópia:

SWIFT
// ============================================
// inout parameter: swapping two variables
// ============================================
func swapValues(_ a: inout Int, _ b: inout Int) {
    let temp = a
    a = b
    b = temp
}
var x = 10
var y = 20
swapValues(&x, &y)
print("x = \(x), y = \(y)")

Saída:

TEXT 📖 Somente leitura
x = 20, y = 10

⚠️ Nota: Prefixe a variável com & ao passar para um parâmetro inout. Você não pode passar constantes ou literais.

▶ Exemplo: Calculadora Universal de Média

SWIFT
// ============================================
// Variadic + inout combined: compute average and track calls
// ============================================
func average(_ scores: Double..., record callCount: inout Int) -> Double {
    callCount += 1
    guard !scores.isEmpty else { return 0 }
    var total = 0.0
    for score in scores {
        total += score
    }
    return total / Double(scores.count)
}
var callTimes = 0
print("Average: \(average(85, 90, 78, record: &callTimes))")
print("Average: \(average(100, 95, record: &callTimes))")
print("Function called \(callTimes) times")

Saída:

TEXT 📖 Somente leitura
Average: 84.33333333333333
Average: 97.5
Function called 2 times

6. Exemplo Completo: Calculadora de Desconto de Pedido

SWIFT
// ============================================
// Full example: Order discount calculator
// Combines argument labels, defaults, variadic, inout
// ============================================
import Foundation
// 1. Compute subtotal (variadic)
func subtotal(_ prices: Double...) -> Double {
    var total = 0.0
    for price in prices {
        total += price
    }
    return total
}
// 2. Apply discount (default parameter + argument label)
func applyDiscount(to total: Double, rate: Double = 0.1) -> Double {
    return total * (1 - rate)
}
// 3. Log orders (inout parameter)
func logOrder(_ description: String, counter: inout Int) {
    counter += 1
    print("[\(counter)] \(description)")
}
// 4. Simulate order processing
var orderCount = 0
let item1 = subtotal(29.99, 49.99)
let item2 = subtotal(9.99, 14.99, 24.99)
logOrder("Item 1 subtotal: $\(item1)", counter: &orderCount)
logOrder("Item 2 subtotal: $\(item2)", counter: &orderCount)
let total1 = applyDiscount(to: item1, rate: 0.15)
let total2 = applyDiscount(to: item2)
let finalTotal = total1 + total2
logOrder("Final total: $\(finalTotal)", counter: &orderCount)

Saída:

TEXT 📖 Somente leitura
[1] Item 1 subtotal: $79.98
[2] Item 2 subtotal: $49.97
[3] Final total: $112.94

❓ Perguntas Frequentes

P: Qual é a diferença entre rótulo de argumento e nome de parâmetro? R: O rótulo de argumento (nome externo) é usado no local da chamada. O nome do parâmetro (nome interno / nome local) é usado dentro do corpo da função. O primeiro serve para legibilidade no local da chamada; o segundo serve para semântica interna. Eles podem ser iguais ou diferentes. P: Como inout difere de uma variável global? R: Um parâmetro inout se comporta como uma variável local dentro da função e grava de volta no original apenas quando a função retorna. Uma variável global pode ser lida e escrita diretamente, mas reduz a manutenibilidade e testabilidade. inout é a escolha mais segura. P: Qual é a diferença entre parâmetros variáveis ​​e de matriz? R: Os parâmetros variáveis ​​não exigem a construção explícita de uma matriz no site de chamada — basta passar valores separados por vírgula. Os parâmetros da matriz requerem o formato [1, 2, 3]. Variádico é mais conciso. P: Uma função pode ter mais de um parâmetro variádico? R: Não. Cada função pode ter no máximo um parâmetro variádico, e ele normalmente deve vir por último na lista de parâmetros. Se você precisar de múltiplos parâmetros de comprimento variável, considere usar parâmetros de array. P: O que uma função retorna quando a seta é omitida? R: Omitir -> Tipo equivale a retornar Void (a tupla vazia ()). O corpo da função pode omitir a instrução return. Por exemplo, func log() { print("log") } retorna Void.


📖 Resumo


📝 Exercícios

  1. Iniciante: Escreva uma função saudar que aceita nome (String) e saudacao (String, padrão "Olá") e imprime uma saudação. Chame-a pelo menos duas vezes usando dois estilos diferentes de rótulo de argumento.
  2. Intermediário: Escreva uma função calcularIMC que aceita peso (kg, Double) e altura (m, Double), retornando o valor do IMC. Use rótulos de argumento para que o local da chamada leia como calcularIMC(peso: 75, altura: 1.8). Adicione também um parâmetro inout para rastrear o número de chamadas.
  3. Desafio: Escreva uma função analisadorNotas que usa parâmetros variádicos para aceitar qualquer número de notas e retorna as notas mais alta, mais baixa e média. Use um parâmetro inout para manter um histórico de análise (adicione a contagem de cada análise a um array). Imprima o histórico no final.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%