Companion object en Kotlin : ce que c'est, syntaxe et utilisation

Auteur : IT Sectr Publié le : 2026-06-21 Temps de lecture : 9 min

companion object est un mécanisme du langage Kotlin qui remplace le mot-clé static de Java pour déclarer des membres statiques d'une classe. Kotlin n'a pas de static intégré — à la place, on utilise une déclaration object avec le modificateur companion à l'intérieur d'une classe. Selon JetBrains, 2025, companion object permet d'appeler des méthodes et des propriétés via le nom de la classe, ce qui en fait l'équivalent complet des membres statiques dans l'écosystème Java.

Points Clés

  • companion object est une déclaration object à l'intérieur d'une classe avec le mot-clé companion, remplaçant Java static
  • Membres statiques accessibles via le nom de la classe sans créer d'instance : ClassName.method()
  • Companion object nommé permet de donner un nom à l'objet pour un code plus lisible
  • Interfaces en Kotlin peuvent également contenir companion object avec implémentation de méthodes
  • @JvmStatic — annotation pour exporter les méthodes de companion object comme de vraies méthodes static en Java

Qu'est-ce que companion object en Kotlin ?

companion object est un type spécial de déclaration object en Kotlin marqué par le mot-clé companion. Il permet de déclarer des membres qui appartiennent à la classe plutôt qu'à ses instances — c'est-à-dire des membres statiques en termes Java. Contrairement à Java, où static est un modificateur pour des champs et méthodes individuels, en Kotlin les membres statiques sont regroupés à l'intérieur d'un seul objet compagnon.

Toute classe en Kotlin peut contenir exactement un companion object. Les membres de cet objet sont accessibles via le nom de la classe sans créer d'instance : MyClass.method(). En termes de bytecode, un companion object est compilé en une classe interne séparée, et ses méthodes deviennent des méthodes statiques de la classe externe lors de l'utilisation de l'annotation @JvmStatic.

Selon Google I/O 2024, companion object est devenu le modèle principal pour les méthodes d'usine, les constantes et les fonctions utilitaires dans les applications Android modernes écrites en Kotlin. Les développeurs le choisissent plutôt que des classes utilitaires avec des fonctions au niveau du package car companion object maintient une connexion logique avec la classe propriétaire.

Utilisez companion object pour regrouper le contexte statique — constantes, usines, méthodes auxiliaires qui appartiennent logiquement à la classe mais ne nécessitent pas d'instance.

Syntaxe de companion object : déclaration et accès

La syntaxe de base de companion object est simple : le mot-clé companion est placé avant la déclaration object à l'intérieur de la classe. Si aucun nom n'est spécifié, l'objet reçoit le nom Companion, qui peut être accédé explicitement ou implicitement.

kotlin
class User {
    companion object {
        const val TABLE_NAME = "users"

        fun create(name: String): User {
            return User(name)
        }
    }

    val name: String
    constructor(name: String) { this.name = name }
}

// Access via class name
val table = User.TABLE_NAME
val user = User.create("Alice")

Dans l'exemple ci-dessus, TABLE_NAME et create() sont accessibles via User.TABLE_NAME et User.create(). Notez le modificateur const pour les constantes primitives — il garantit l'insertion de la valeur à la compilation, similaire à Java static final pour les primitifs et String.

Accès implicite et explicite via Companion

Si un companion object n'a pas de nom, on peut y accéder via le nom automatique Companion : User.Companion.TABLE_NAME. En pratique, cela est rarement nécessaire, mais utile lors de l'appel depuis du code Java ou lors de l'utilisation de la réflexion.

kotlin
// Both calls are equivalent
User.create("Bob")
User.Companion.create("Bob")

// Getting reference to companion object
val companion: User.Companion = User

Companion object nommé et caractéristiques

Un companion object peut avoir un nom, ce qui améliore la lisibilité du code et permet d'y accéder par un nom significatif. Factory est le nom le plus courant pour un companion object utilisé comme usine.

kotlin
class HttpResponse {
    companion object Factory {
        fun ok(body: String): HttpResponse = HttpResponse(200, body)
        fun notFound(): HttpResponse = HttpResponse(404, "Not Found")
        fun serverError(): HttpResponse = HttpResponse(500, "Internal Error")
    }
}

// Access via Factory name
val response = HttpResponse.Factory.ok("data")

Un companion object nommé aide à documenter le but des membres statiques. En refactorisation, le nom rend le code auto-documenté — le développeur voit instantanément que Factory crée des instances de HttpResponse.

Limitation : exactement un companion object par classe

Une classe ne peut contenir qu'un seul companion object. C'est une différence fondamentale avec Java, où vous pouvez déclarer n'importe quel nombre de champs et méthodes statiques sans regroupement. Si vous avez besoin de plusieurs groupes logiques de membres statiques, utilisez des déclarations object imbriquées sans companion.

Selon la documentation officielle de Kotlin (Kotlin Docs, 2025), la limitation d'un seul companion object est motivée par la conception du langage : les membres statiques doivent être étroitement couplés avec la classe, et un objet compagnon fournit une limite claire pour cette connexion. S'il y a trop de membres statiques, c'est un signal pour refactoriser la classe.

Companion object dans les interfaces

En Kotlin, les interfaces peuvent également contenir un companion object. Cela permet de définir des méthodes statiques et des constantes directement à l'intérieur d'une interface, ce qui n'est pas possible en Java. Cette approche est souvent utilisée pour déclarer des constantes liées à l'interface ou des méthodes d'usine.

kotlin
interface ApiService {
    companion object {
        const val BASE_URL = "https://api.example.com"
        const val TIMEOUT_MS = 5000

        fun create(client: OkHttpClient): ApiService =
            Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client)
                .build()
                .create(ApiService::class.java)
    }
}

Dans cet exemple, BASE_URL, TIMEOUT_MS et create() appartiennent à l'interface ApiService, pas à ses implémentations. C'est pratique : toutes les constantes et la logique d'usine pour créer une instance de service API se trouvent à un seul endroit — à l'intérieur de l'interface elle-même.

Les implémentations d'interface n'héritent pas des membres du companion object — ils sont appelés uniquement via le nom de l'interface : ApiService.BASE_URL.

@JvmStatic et @JvmField : compatibilité Java

Lors de l'appel de méthodes de companion object depuis du code Java, par défaut elles sont accessibles comme des méthodes de la classe interne Companion, pas comme des méthodes statiques de la classe externe. Pour les exporter comme de vraies méthodes et champs statiques pour Java, utilisez l'annotation @JvmStatic pour les méthodes et @JvmField pour les champs.

AnnotationApplicationRésultat en Java
@JvmStaticMéthodes de companion objectMéthode statique : ClassName.method()
@JvmFieldChamps de companion objectChamp statique : ClassName.field
constPrimitifs et StringConstante inline : le compilateur substitue la valeur
sans annotationMéthodes/champs par défautCompanion.method() / Companion.field
kotlin
class MathUtils {
    companion object {
        const val PI = 3.14159

        @JvmStatic
        fun square(x: Int): Int = x * x

        @JvmField
        val TAG: String = "MathUtils"
    }
}

// Called in Java as MathUtils.square(5), MathUtils.TAG

L'utilisation de @JvmStatic est recommandée pour toutes les méthodes publiques de companion object qui doivent être accessibles depuis du code Java. const s'applique uniquement aux types primitifs et String — pour les autres types, utilisez @JvmField.

Exemples pratiques d'utilisation de companion object

Dans les projets réels, companion object est utilisé pour plusieurs scénarios standards. Les méthodes d'usine sont le modèle le plus courant : au lieu de plusieurs constructeurs avec des signatures différentes, on utilise des méthodes d'usine nommées dans companion object.

kotlin
sealed class NetworkResult<out T> {
    data class Success<out T>(val data: T) : NetworkResult<T>()
    data class Error(val message: String) : NetworkResult<Nothing>()

    companion object {
        fun loading<T>(): NetworkResult<T> =
            Loading()
    }
}

private class Loading<T> : NetworkResult<T>()

companion object dans NetworkResult fournit une méthode d'usine loading() qui crée une instance Loading avec le bon type générique. Sans cette méthode, vous devriez créer une instance directement via Loading(), ce qui expose l'implémentation interne.

Constantes et tags de journalisation

companion object est souvent utilisé pour stocker des constantes spécifiques à la classe. Les constantes déclarées avec const val sont insérées à la compilation, offrant une surcharge nulle à l'exécution.

kotlin
class UserRepository {
    companion object {
        private const val TAG = "UserRepository"
        private const val CACHE_SIZE = 100
        private const val DEFAULT_PAGE_SIZE = 20
    }
}

Questions Fréquentes

Quelle est la différence entre companion object et un object normal en Kotlin ?

Un object normal est un singleton à part entière qui existe indépendamment de la classe. companion object est un object à l'intérieur d'une classe dont les membres sont appelés via le nom de la classe externe. En bytecode, un companion object devient une classe imbriquée statique, tandis qu'un object normal devient une classe singleton autonome.

Peut-on hériter de companion object ?

Non, companion object n'est pas hérité par les sous-classes. Si la classe B étend la classe A, alors B.method() n'appellera pas la méthode du companion object de la classe A — vous devez appeler A.method(). Cela correspond au comportement des méthodes statiques en Java.

Comment appeler companion object depuis du code Java ?

Par défaut — via ClassName.Companion.method(). Pour l'appeler comme méthode statique, ajoutez @JvmStatic à la méthode du companion object. Pour les champs, utilisez @JvmField ou déclarez-les avec const val pour les primitifs.

Pourquoi n'y a-t-il pas de mot-clé static en Kotlin ?

Les développeurs de Kotlin ont décidé d'abandonner static au profit de companion object pour un travail uniforme avec les objets. static en Java viole les principes POO car les méthodes statiques ne sont pas liées à une instance. companion object est un objet de première classe qui peut être passé, étendu avec des fonctions d'extension et implémenter des interfaces.

Est-ce que companion object affecte les performances ?

En utilisant const val pour les primitifs et String — surcharge nulle, la valeur est insérée dans le bytecode. Pour les méthodes, il n'y a pas de surcharge à moins que la méthode soit inline. Dans la plupart des cas, companion object ne crée aucun impact mesurable sur les performances. Utilisez @JvmStatic uniquement pour l'API publique appelée depuis Java.

Résumé

  • companion object est un mécanisme Kotlin pour déclarer des membres statiques de classe, remplaçant Java static
  • Un companion object par classe — regroupe tous les éléments statiques dans un seul objet compagnon
  • Accès via le nom de la classe : ClassName.method() ou ClassName.Companion.method()
  • @JvmStatic et @JvmField exportent les membres comme de vraies méthodes et champs statiques pour Java
  • const val pour les primitifs et String — insère la valeur à la compilation avec une surcharge nulle
  • Interfaces supportent également companion object pour les constantes et méthodes d'usine
  • Companion object nommé améliore la lisibilité du code et auto-documente le but des membres statiques

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi