web-dev-qa-db-fra.com

Les constantes dans Kotlin - Quelle est la méthode recommandée pour les créer?

Comment est-il recommandé de créer des constantes dans Kotlin? Et quelle est la convention de nommage? Je n'ai pas trouvé cela dans la documentation.

companion object {
    //1
    val MY_CONST = "something"

    //2
    const val MY_CONST = "something"

    //3
    val myConst = "something"
}

Ou ...?

59
Jodimoro

En Kotlin, si vous voulez créer les constantes locales censées être utilisées dans la classe, vous pouvez le créer comme ci-dessous.

val MY_CONSTANT = "Constants"

Et si vous voulez créer une constante publique dans kotlin telle que public static final en Java, vous pouvez la créer comme suit.

companion object{

     const val MY_CONSTANT = "Constants"

}
59
AaRiF

Évitez d'utiliser des objets de compagnie. Derrière le capot, une méthode d'instance getter et setter est créée pour rendre les champs accessibles et l'appel de méthodes d'instance est techniquement plus coûteux que l'appel de méthodes statiques.

public class DbConstants {
    companion object {
        val TABLE_USER_ATTRIBUTE_EMPID = "_id"
        val TABLE_USER_ATTRIBUTE_DATA = "data"
    }

Définissez plutôt les constantes dans object.

Pratique recommandée :

object DbConstants {
        const val TABLE_USER_ATTRIBUTE_EMPID = "_id"
        const val TABLE_USER_ATTRIBUTE_DATA = "data"
}

et accédez-y globalement comme ceci: DbConstants.TABLE_USER_ATTRIBUTE_EMPID

31
sudesh

Les valeurs connues au moment de la compilation peuvent (et devraient à mon avis) être marquées comme constantes.

Les conventions de dénomination doivent suivre les règles Java et être correctement visibles lorsqu'elles sont utilisées à partir de code Java (c'est difficile à obtenir avec des objets compagnons, mais quoi qu'il en soit).

Les déclarations de constante appropriées sont:

const val MY_CONST = "something"
const val MY_INT = 1
15
piotrpo

Vous n'avez pas besoin d'une classe, d'un objet ou d'un objet compagnon pour déclarer des constantes dans Kotlin. Vous pouvez simplement déclarer un fichier contenant toutes les constantes (par exemple, Constants.kt) et déclarer directement les constantes à l'intérieur du fichier. Les constantes connues au moment de la compilation doivent être marquées avec const.

Donc, dans ce cas, cela devrait être:

const val MY_CONST = "something"

et ensuite vous pouvez importer la constante en utilisant:

import package_name.MY_CONST

Vous pouvez vous référer à ce link

8
Abdul Wadood

Tout d’abord , la convention de dénomination dans Kotlin pour les constantes est la même que dans Java (par exemple: MY_CONST_IN_UPPERCASE).

Comment dois-je le créer?

1. En tant que valeur de niveau supérieur (recommandé)

Vous devez simplement mettre votre const outside votre déclaration de classe.

Deux possibilités : Déclarez votre const dans votre fichier de classe (votre const a une relation claire avec votre classe)

private const val CONST_USED_BY_MY_CLASS = 1

class MyClass { 
    // I can use my const in my class body 
}

Créez un fichier constants.kt dédié dans lequel stocker ces const globaux (ici, vous voulez utiliser votre const de manière étendue dans votre projet):

package com.project.constants
const val URL_PATH = "https:/"

Ensuite, il vous suffit de l'importer où vous en avez besoin:

import com.project.constants

MyClass {
    private fun foo() {
        val url = URL_PATH
        System.out.print(url) // https://
    }
}

2. Déclarez-le dans un objet compagnon (ou une déclaration d'objet)

C'est beaucoup less cleaner car sous le capot, lors de la génération de bytecode, un objet inutile est créé:

MyClass {
    companion object {
        private const val URL_PATH = "https://"
        const val PUBLIC_URL_PATH = "https://public" // Accessible in other project files via MyClass.PUBLIC_URL_PATH
    }
}

Encore pire si vous le déclarez en tant que val au lieu de const (le compilateur générera un objet inutile + une fonction inutile):

MyClass {
    companion object {
        val URL_PATH = "https://"
    }
}

Remarque :

Dans kotlin, const ne peut contenir que des types primitifs. Si vous souhaitez lui transmettre une fonction, vous devez ajouter l'annotation @JvmField. Au moment de la compilation, il sera transformé en une variable finale statique publique. Mais c'est plus lent qu'avec un type primitif. Essayez de l'éviter.

@JvmField val foo = Foo()
4
A.Mamode

Si vous mettez votre const val valName = valValue devant le nom de la classe, cela créera un

public static final YourClass.Kt qui aura les valeurs public static final.

Kotlin :

const val MY_CONST0 = 0
const val MY_CONST1 = 1
data class MyClass(var some: String)

Java décompilé:

public final class MyClassKt {
    public static final int MY_CONST0 = 0;
    public static final int MY_CONST1 = 1;
}
// rest of MyClass.Java
2
Thales Araujo

Quelque chose qui n'est mentionné dans aucune des réponses est la surcharge liée à l'utilisation de companion objects. Comme vous pouvez le lire ici , les objets compagnons sont en fait des objets et leur création consomme des ressources. En outre, vous devrez peut-être utiliser plusieurs fonctions de lecture à chaque fois que vous utilisez votre constante. Si vous n'avez besoin que de quelques constantes primitives, vous ferez probablement mieux d'utiliser val pour obtenir un better performance et éviter le companion object.

TL; DR; de l'article:

L'utilisation d'un objet compagnon transforme réellement ce code

class MyClass {

    companion object {
        private val TAG = "TAG"
    }

    fun helloWorld() {
        println(TAG)
    }
}

Dans ce code:

public final class MyClass {
    private static final String TAG = "TAG";
    public static final Companion companion = new Companion();

    // synthetic
    public static final String access$getTAG$cp() {
        return TAG;
    }

    public static final class Companion {
        private final String getTAG() {
            return MyClass.access$getTAG$cp();
        }

        // synthetic
        public static final String access$getTAG$p(Companion c) {
            return c.getTAG();
        }
    }

    public final void helloWorld() {
        System.out.println(Companion.access$getTAG$p(companion));
    }
}

Alors essayez de les éviter.

2
Sir Codesalot

constantes locales:

const val NAME = "name"

Constantes globales:

object MyConstants{
    val NAME = "name"
    val ID = "_id"
    var EMAIL = "email"
}

accéder à MyConstants.NAME

1
Amjed Baig

Commander cet article . Il donne un bon aperçu des différentes manières dont vous pouvez stocker vos constantes, avec des compromis de performance associés. 

1
sarpu
class Myclass {

 companion object {
        const val MYCONSTANT = 479
}

vous avez deux choix: vous pouvez utiliser le mot clé const ou le @JvmField, ce qui en fait une constante statique finale de Java. 

class Myclass {

     companion object {
           @JvmField val MYCONSTANT = 479
    }

Si vous utilisez l'annotation @JvmField, une fois compilée, la constante est insérée comme vous le feriez pour Java.
Tout comme vous l'appelez en Java, le compilateur le remplace pour vous lorsque vous appelez la constante compagnon en code. 

Toutefois, si vous utilisez le mot-clé const, la valeur de la constante est alors en ligne. Par inline, je veux dire que la valeur réelle est utilisée après sa compilation. 

pour résumer, voici ce que le compilateur fera pour vous:

//so for @JvmField:

Foo var1 = Constants.FOO;

//and for const:

Foo var1 = 479
1
j2emanue

Il y a plusieurs façons de définir des constantes dans Kotlin,

tilisation d'un objet compagnon

    companion object {
        const val ITEM1 = "item1"
        const val ITEM2 = "item2"
    }

vous pouvez utiliser le bloc d'objet compagnon ci-dessus dans n'importe quelle classe et définir tous vos champs à l'intérieur de ce bloc lui-même. Mais il y a un problème avec cette approche, dit la documentation,

même si les membres des objets compagnon ressemblent à des membres statiques dans d'autres langages, ceux-ci sont toujours, au moment de l'exécution, des membres d'instance d'objets réels et peuvent, par exemple, implémenter des interfaces.

Lorsque vous créez vos constantes à l'aide d'un objet compagnon et que vous voyez le bytecode décompilé, vous obtiendrez quelque chose comme ci-dessous,

  ClassName.Companion Companion = ClassName.Companion.$$INSTANCE;
  @NotNull
  String ITEM1 = "item1";
  @NotNull
  String ITEM2 = "item2";

  public static final class Companion {
     @NotNull
     private static final String ITEM1 = "item1";
     @NotNull
     public static final String ITEM2 = "item2";

     // $FF: synthetic field
     static final ClassName.Companion $$INSTANCE;

     private Companion() {
     }

     static {
        ClassName.Companion var0 = new ClassName.Companion();
        $$INSTANCE = var0;
     }
  }

À partir de là, vous pouvez facilement voir ce que dit la documentation, même si les membres des objets compagnons ressemblent à des membres statiques dans d'autres langues, ceux-ci sont toujours des membres d'instances d'objets réels C'est un travail supplémentaire qui n'est pas requis.

Maintenant vient une autre façon, où nous n'avons pas besoin d'utiliser d'objet compagnon comme ci-dessous,

object ApiConstants {
      val ITEM1: String = "item1"
 }

Encore une fois si vous voyez la version décompilée du code d'octet de l'extrait ci-dessus, vous trouverez quelque chose comme ça,

public final class ApiConstants {
     private static final String ITEM1 = "item1";

     public static final ApiConstants INSTANCE;

     public final String getITEM1() {
           return ITEM1;
      }

     private ApiConstants() {
      }

     static {
         ApiConstants var0 = new ApiConstants();
         INSTANCE = var0;
         CONNECT_TIMEOUT = "item1";
      }
    }

Maintenant, si vous voyez le code décompilé ci-dessus, il crée une méthode get pour chaque variable. Cette méthode get n'est pas obligatoire du tout.

Pour se débarrasser de ces méthodes get, vous devez utiliser const avant val comme ci-dessous,

object ApiConstants {
     const val ITEM1: String = "item1"
 }

Maintenant, si vous voyez le code décompilé de l'extrait ci-dessus, vous verrez qu'il est plus facile à lire car c'est la moindre conversion en arrière-plan pour votre code.

public final class ApiConstants {
    public static final String ITEM1 = "item1";
    public static final ApiConstants INSTANCE;

    private ApiConstants() {
     }

    static {
        ApiConstants var0 = new ApiConstants();
        INSTANCE = var0;
      }
    }

C'est donc le meilleur moyen de créer des constantes.

0
Abhishek Kumar

Pour les primitives et les chaînes:

/** The empty String. */
const val EMPTY_STRING = ""

Pour les autres cas:

/** The empty array of Strings. */
@JvmField val EMPTY_STRING_ARRAY = arrayOfNulls<String>(0)

Exemple:

/*
 * Copyright 2018 Vorlonsoft LLC
 *
 * Licensed under The MIT License (MIT)
 */

package com.vorlonsoft.Android.rate

import com.vorlonsoft.Android.rate.Constants.Utils.Companion.UTILITY_CLASS_MESSAGE

/**
 * Constants Class - the constants class of the AndroidRate library.
 *
 * @constructor Constants is a utility class and it can't be instantiated.
 * @since       1.1.8
 * @version     1.2.1
 * @author      Alexander Savin
 */
internal class Constants private constructor() {
    /** Constants Class initializer block. */
    init {
        throw UnsupportedOperationException("Constants$UTILITY_CLASS_MESSAGE")
    }

    /**
     * Constants.Date Class - the date constants class of the AndroidRate library.
     *
     * @constructor Constants.Date is a utility class and it can't be instantiated.
     * @since       1.1.8
     * @version     1.2.1
     * @author      Alexander Savin
     */
    internal class Date private constructor() {
        /** Constants.Date Class initializer block. */
        init {
            throw UnsupportedOperationException("Constants.Date$UTILITY_CLASS_MESSAGE")
        }

        /** The singleton contains date constants. */
        companion object {
            /** The time unit representing one year in days. */
            const val YEAR_IN_DAYS = 365.toShort()
        }
    }

    /**
     * Constants.Utils Class - the utils constants class of the AndroidRate library.
     *
     * @constructor Constants.Utils is a utility class and it can't be instantiated.
     * @since       1.1.8
     * @version     1.2.1
     * @author      Alexander Savin
     */
    internal class Utils private constructor() {
        /** Constants.Utils Class initializer block. */
        init {
            throw UnsupportedOperationException("Constants.Utils$UTILITY_CLASS_MESSAGE")
        }

        /** The singleton contains utils constants. */
        companion object {
            /** The empty String. */
            const val EMPTY_STRING = ""
            /** The empty array of Strings. */
            @JvmField val EMPTY_STRING_ARRAY = arrayOfNulls<String>(0)
            /** The part 2 of a utility class unsupported operation exception message. */
            const val UTILITY_CLASS_MESSAGE = " is a utility class and it can't be instantiated!"
        }
    }
}
0
Alexander Savin