0Pricing
Kotlin Academy · Aula

Mecanismo expect/actual para APIs de plataforma

Declare declarações esperadas no código comum e forneça implementações reais por plataforma.

Mecanismo expect/actual para APIs de plataforma é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.

O padrão expect/actual

expect declara um contrato de API em commonMain. Cada plataforma fornece uma implementação actual. O compilador garante que todos os destinos tenham uma implementação actual.

// commonMain:
expect fun platformName(): String

// androidMain:
actual fun platformName(): String = "Android ${android.os.Build.VERSION.SDK_INT}"

// iosMain:
actual fun platformName(): String = UIDevice.currentDevice.systemName()

classe expect

expect class declara uma classe com sua API em commonMain. Cada plataforma fornece a implementação completa.

// commonMain:
expect class DateTime {
    fun format(pattern: String): String
    val timestamp: Long
}

// androidMain:
actual class DateTime {
    actual val timestamp = System.currentTimeMillis()
    actual fun format(pattern: String): String =
        java.text.SimpleDateFormat(pattern).format(java.util.Date(timestamp))
}

objeto expect

expect object declara um singleton com seu contrato. É útil para utilitários específicos da plataforma, como registro em log, configurações ou análises.

// commonMain:
expect object Logger {
    fun debug(msg: String)
    fun error(msg: String, cause: Throwable? = null)
}

// androidMain:
actual object Logger {
    actual fun debug(msg: String) = android.util.Log.d("App", msg)
    actual fun error(msg: String, cause: Throwable?) =
        android.util.Log.e("App", msg, cause)
}

expect val / fun no nível superior

expect val e expect fun no nível superior são simples e funcionam bem para utilitários de plataforma sem estado.

// commonMain:
expect val isDebugBuild: Boolean
expect fun generateUUID(): String

// androidMain:
actual val isDebugBuild: Boolean = BuildConfig.DEBUG
actual fun generateUUID(): String = java.util.UUID.randomUUID().toString()

// iosMain:
actual val isDebugBuild: Boolean = false // or a native flag
actual fun generateUUID(): String = NSUUID().UUIDString()

expect fun com implementação padrão

A partir do Kotlin 1.9+, expect fun pode ter uma implementação padrão por meio de expect fun f() { }. As plataformas podem substituir a implementação padrão ou usá-la.

// commonMain (Kotlin 1.9+):
expect fun log(msg: String) {
    println("[DEFAULT] $msg") // used if no actual overrides
}

// androidMain:
actual fun log(msg: String) = android.util.Log.d("KMP", msg)

// iosMain (uses default):
// no actual needed — default is used

Alias de tipo actual

Se uma plataforma já tiver exatamente a classe de que você precisa, use actual typealias para apontar para ela em vez de envolvê-la.

// commonMain:
expect class AtomicInt {
    fun get(): Int
    fun incrementAndGet(): Int
}

// androidMain / jvmMain:
actual typealias AtomicInt = java.util.concurrent.atomic.AtomicInteger

// iosMain:
actual class AtomicInt {
    private var value = 0
    actual fun get() = value
    actual fun incrementAndGet() = ++value
}

interface expect (padrão indireto)

Para obter mais flexibilidade, declare uma interface em commonMain e use expect/actual somente para a fábrica que cria a instância da plataforma.

// commonMain:
interface FileStorage {
    suspend fun readFile(path: String): ByteArray
    suspend fun writeFile(path: String, data: ByteArray)
}
expect fun createFileStorage(): FileStorage

// androidMain:
actual fun createFileStorage(): FileStorage = AndroidFileStorage()

// iosMain:
actual fun createFileStorage(): FileStorage = IosFileStorage()

Testes com expect/actual

Em commonTest, teste a API comum. As implementações actual são executadas durante as tarefas de teste específicas da plataforma (testDebugUnitTest no Android, iosX64Test no iOS).

// commonTest:
import kotlin.test.Test
import kotlin.test.assertNotNull
class PlatformTest {
    @Test
    fun testUUID() {
        val uuid = generateUUID()
        assertNotNull(uuid)
        println("UUID: $uuid")
    }
}

Armadilhas comuns

Cada expect declarado deve ter um actual em TODOS os destinos configurados, caso contrário a compilação falha. As implementações actual ausentes são detectadas em tempo de compilação.

// If you add a new target (e.g., jvmMain), you must add:
// actual fun platformName(): String = "JVM"
// Otherwise:
// error: Expected function platformName has no actual declaration in module :shared for JVM
fun main() { println("Missing actuals = compile error") }

Classe de anotação expect

expect annotation class permite o mapeamento de anotações específicas da plataforma — por exemplo, mapear uma anotação comum semelhante a @Parcelize para o plug-in Parcelize do Android.

// commonMain:
expect annotation class CommonParcelize()

// androidMain:
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
actual annotation class CommonParcelize

// iosMain:
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
actual annotation class CommonParcelize

Exemplo real: Keychain/Preferences

Um exemplo típico de expect/actual do mundo real é uma interface de armazenamento seguro em que o Android usa EncryptedSharedPreferences e o iOS usa Keychain.

// commonMain:
expect class SecureStorage {
    fun save(key: String, value: String)
    fun get(key: String): String?
}

// androidMain:
actual class SecureStorage {
    private val prefs = /* EncryptedSharedPreferences */ mapOf<String,String>()
    actual fun save(key: String, value: String) { /* ... */ }
    actual fun get(key: String): String? = null // simplified
}

Verificação rápida

O que acontece em tempo de compilação se uma declaração expect não tiver um actual para um destino?

Recapitulação

expect declara a API em commonMain. actual fornece a implementação da plataforma. Use actual typealias quando a plataforma já tiver o tipo necessário. As implementações actual ausentes são detectadas em tempo de compilação — sem surpresas em tempo de execução.

Perguntas Frequentes

A aula “Mecanismo expect/actual para APIs de plataforma” é grátis?

Sim — o texto completo de “Mecanismo expect/actual para APIs de plataforma” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.

O que vou aprender em “Mecanismo expect/actual para APIs de plataforma”?

Declare declarações esperadas no código comum e forneça implementações reais por plataforma. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Kotlin Academy?

Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Mecanismo expect/actual para APIs de plataforma”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Kotlin Academy?

Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Estrutura de projeto KMP: commonMain, androidMain, iosMain
  2. Mecanismo expect/actual para APIs de plataforma
  3. Compartilhando camadas de repositório e casos de uso
  4. Injeção de dependências em KMP com Koin
← Voltar para Kotlin Academy