wake-up-neo.com

Konstanten in Kotlin - wie werden sie empfohlen?

Wie ist es empfehlenswert, Konstanten in Kotlin zu erstellen? Und was ist die Namenskonvention? Das habe ich in der Dokumentation nicht gefunden.

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

    //2
    const val MY_CONST = "something"

    //3
    val myConst = "something"
}

Oder ...?

59
Jodimoro

Wenn Sie in Kotlin die lokalen Konstanten erstellen möchten, die in der Klasse verwendet werden sollen, können Sie sie wie folgt erstellen

val MY_CONSTANT = "Constants"

Wenn Sie eine öffentliche Konstante in kotlin wie public static final in Java erstellen möchten, können Sie sie wie folgt erstellen.

companion object{

     const val MY_CONSTANT = "Constants"

}
59
AaRiF

Vermeiden Sie die Verwendung von Begleitobjekten. Hinter der Haube werden Getter- und Setter-Instanzmethoden erstellt, damit die Felder zugänglich sind und der Aufruf von Instanzmethoden technisch teurer ist als der Aufruf statischer Methoden.

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

Definieren Sie stattdessen die Konstanten in object.

Empfohlene Praxis :

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

und greifen Sie global auf diese zu: DbConstants.TABLE_USER_ATTRIBUTE_EMPID

31
sudesh

Zur Kompilierzeit bekannte Werte können (und sollten meiner Meinung nach) als konstant markiert werden.

Namenskonventionen sollten Java-Konventionen folgen und sollten bei Verwendung von Java-Code gut sichtbar sein (mit Begleitobjekten ist das irgendwie schwierig, aber trotzdem).

Die richtigen Konstantenerklärungen sind:

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

Sie benötigen keine Klasse, kein Objekt oder ein Begleitobjekt, um Konstanten in Kotlin zu deklarieren. Sie können einfach eine Datei deklarieren, die alle Konstanten enthält (beispielsweise Constants.kt), und die Konstanten direkt in der Datei deklarieren. Die zur Kompilierzeit bekannten Konstanten müssen mit const gekennzeichnet sein.

In diesem Fall sollte es also sein:

const val MY_CONST = "something"

und dann können Sie die Konstante importieren mit:

import package_name.MY_CONST

Sie können sich auf diesen Link beziehen

8
Abdul Wadood

Zuallererst ist die Namenskonvention in Kotlin für Konstanten dieselbe wie in Java (z. B .: MY_CONST_IN_UPPERCASE).

Wie soll ich es schaffen?

1. Als Top-Level-Wert (empfohlen)

Sie müssen nur Ihre const außerhalb Ihre Klassendeklaration setzen.

Zwei Möglichkeiten : Deklarieren Sie Ihre const in Ihrer Klassendatei (Ihre const haben eine klare Beziehung zu Ihrer Klasse)

private const val CONST_USED_BY_MY_CLASS = 1

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

Erstellen Sie eine dedizierte constants.kt-Datei, in der diese globalen const gespeichert werden sollen (hier möchten Sie Ihre const im gesamten Projekt verwenden):

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

Dann müssen Sie es nur noch dort importieren, wo Sie es brauchen:

import com.project.constants

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

2. Deklarieren Sie es in einem Begleitobjekt (oder einer Objektdeklaration).

Das ist viel weniger sauberer, weil unter der Haube, wenn der Bytecode generiert wird, ein nutzloses Objekt erzeugt wird:

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
    }
}

Schlimmer noch wenn Sie es als Wert anstelle einer Konstante deklarieren (Compiler erzeugt ein unbrauchbares Objekt + eine unbrauchbare Funktion):

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

Hinweis :

In Kotlin kann const nur primitive Typen enthalten. Wenn Sie eine Funktion übergeben möchten, müssen Sie die Annotation @JvmField hinzufügen. Zur Kompilierungszeit wird es als öffentliche statische Endvariable transformiert. Aber es ist langsamer als bei einem primitiven Typ. Versuche es zu vermeiden.

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

Wenn Sie Ihren const val valName = valValue vor den Klassennamen setzen, wird auf diese Weise ein erstellt

public static final YourClass.Kt, der die public static final-Werte haben wird.

Kotlin :

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

Java dekompiliert:

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

Etwas, das in keiner der Antworten erwähnt wird, ist der Aufwand für die Verwendung von companion objects. Wie Sie hier lesen können, sind Begleitobjekte tatsächlich Objekte, deren Erstellung Ressourcen erfordert. Darüber hinaus müssen Sie möglicherweise jedes Mal, wenn Sie Ihre Konstante verwenden, mehr als eine Getter-Funktion ausführen. Wenn Sie nur ein paar primitive Konstanten benötigen, ist es wahrscheinlich besser, val zu verwenden, um eine bessere Leistung zu erhalten und den companion object zu vermeiden.

TL; DR; des Artikels:

Durch die Verwendung eines Begleitobjekts wird dieser Code tatsächlich geändert

class MyClass {

    companion object {
        private val TAG = "TAG"
    }

    fun helloWorld() {
        println(TAG)
    }
}

In diesen 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));
    }
}

Versuchen Sie also, sie zu vermeiden.

2
Sir Codesalot

lokale Konstanten:

const val NAME = "name"

Globale Konstanten:

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

greifen Sie auf MyConstants.NAME zu

1
Amjed Baig

Kasse dieser Artikel . Es gibt einen schönen Überblick über verschiedene Möglichkeiten, wie Sie Ihre Konstanten speichern können, und zwar mit entsprechenden Leistungsabwägungen. 

1
sarpu
class Myclass {

 companion object {
        const val MYCONSTANT = 479
}

sie haben zwei Möglichkeiten, das const-Schlüsselwort oder den @JvmField zu verwenden, wodurch es zu einer statischen Endkonstante von Java wird. 

class Myclass {

     companion object {
           @JvmField val MYCONSTANT = 479
    }

Wenn Sie die Annotation @JvmField verwenden, wird die Konstante nach dem Kompilieren so eingefügt, wie Sie sie in Java aufrufen würden.
So wie Sie es in Java aufrufen würden, ersetzt der Compiler das für Sie, wenn Sie die begleitende Konstante im Code aufrufen. 

Wenn Sie jedoch das Schlüsselwort const verwenden, wird der Wert der Konstante eingebettet. Mit Inline meine ich, dass der tatsächliche Wert verwendet wird, nachdem er kompiliert wurde. 

zusammenfassend wird der Compiler Folgendes für Sie tun:

//so for @JvmField:

Foo var1 = Constants.FOO;

//and for const:

Foo var1 = 479
1
j2emanue

Es gibt verschiedene Möglichkeiten, Konstanten in Kotlin zu definieren:

Begleitobjekt verwenden

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

sie können den obigen Begleitobjektblock in jeder Klasse verwenden und alle Ihre Felder in diesem Block selbst definieren. Aber es gibt ein Problem mit diesem Ansatz, heißt es in der Dokumentation,

auch wenn die Mitglieder von Begleitobjekten in anderen Sprachen wie statische Mitglieder aussehen, sind sie zur Laufzeit immer noch Instanzmitglieder realer Objekte und können beispielsweise Schnittstellen implementieren.

Wenn Sie Ihre Konstanten mit dem Companion-Objekt erstellen und den dekompilierten Bytecode sehen, sehen Sie wie folgt aus:

  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;
     }
  }

Von hier aus können Sie leicht sehen, was in der Dokumentation steht , obwohl die Mitglieder von Begleitobjekten in anderen Sprachen wie statische Mitglieder aussehen. Zur Laufzeit sind dies immer noch Instanzmitglieder von realen Objekten zusätzliche Arbeit als erforderlich.

Jetzt kommt ein anderer Weg, wo wir kein Begleitobjekt wie unten verwenden müssen,

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

Wiederum, wenn Sie die dekompilierte Version des Byte-Codes des obigen Snippets sehen, werden Sie so etwas finden:

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";
      }
    }

Wenn Sie nun den oben dekompilierten Code sehen, wird für jede Variable eine get-Methode erstellt. Diese get-Methode ist überhaupt nicht erforderlich.

Um diese get-Methoden loszuwerden, sollten Sie const vor val verwenden. Wie unten,

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

Wenn Sie nun den dekompilierten Code des obigen Snippets sehen, wird das Lesen erleichtert, da die Hintergrundkonvertierung für Ihren Code am geringsten ist.

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

    private ApiConstants() {
     }

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

Dies ist also der beste Weg, um Konstanten zu erstellen.

0
Abhishek Kumar

Für Primitive und Strings:

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

Für andere Fälle:

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

Beispiel:

/*
 * 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