Kotlinで定数を作成することはどのように推奨されますか?そして、命名規則は何ですか?ドキュメントではそれが見つかりません。
companion object {
//1
val MY_CONST = "something"
//2
const val MY_CONST = "something"
//3
val myConst = "something"
}
または...?
Kotlinで定数を作成することはどのように推奨されますか?そして、命名規則は何ですか?ドキュメントではそれが見つかりません。
companion object {
//1
val MY_CONST = "something"
//2
const val MY_CONST = "something"
//3
val myConst = "something"
}
または...?
回答:
Kotlinで、クラスで使用されることになっているローカル定数を作成したい場合は、以下のように作成できます
val MY_CONSTANT = "Constants"
そして、Javaのpublic static finalのようにkotlinでpublic定数を作成する場合は、次のように作成できます。
companion object{
const val MY_CONSTANT = "Constants"
}
Constants.kt
か?
companion object
。@ piotrpoの回答は受け入れられるべきだと思います
コンパニオンオブジェクトの使用は避けてください。内部では、フィールドにアクセスできるように、getterおよびsetterインスタンスメソッドが作成されます。インスタンスメソッドの呼び出しは、静的メソッドの呼び出しよりも技術的に高価です。
public class DbConstants {
companion object {
val TABLE_USER_ATTRIBUTE_EMPID = "_id"
val TABLE_USER_ATTRIBUTE_DATA = "data"
}
代わりに、定数をで定義しますobject
。
推奨プラクティス:
object DbConstants {
const val TABLE_USER_ATTRIBUTE_EMPID = "_id"
const val TABLE_USER_ATTRIBUTE_DATA = "data"
}
次のようにグローバルにアクセスします。
DbConstants.TABLE_USER_ATTRIBUTE_EMPID
const val
コンパニオンオブジェクトでは、より任意の異なる場合がconst val
通常のオブジェクトで(あなたの例の間、すなわち唯一の違いは、省略することをあるように思わconst
コンパニオンオブジェクトの場合には-あなたが追加した場合const
、例は、同じ性能を持つ必要があります)
const val
、aを宣言するのcompanion object
が適切です。
まず、定数のKotlinの命名規則は、Javaの場合と同じです(例:MY_CONST_IN_UPPERCASE)。
const をクラス宣言の外に置くだけです。
2つの可能性:クラスファイルでconstを宣言します(constはクラスと明確な関係があります)
private const val CONST_USED_BY_MY_CLASS = 1
class MyClass {
// I can use my const in my class body
}
これらのグローバルconstを保存する専用のconstants.ktファイルを作成します(ここでは、プロジェクト全体でconstを広く使用したいと思います)。
package com.project.constants
const val URL_PATH = "https:/"
次に、必要な場所にインポートするだけです。
import com.project.constants
MyClass {
private fun foo() {
val url = URL_PATH
System.out.print(url) // https://
}
}
内部的にはバイトコードが生成されると、役に立たないオブジェクトが作成されるため、これはあまりクリーンではありません。
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
}
}
constの代わりにvalとして宣言するとさらに悪い(コンパイラーは役に立たないオブジェクト+役に立たない関数を生成します):
MyClass {
companion object {
val URL_PATH = "https://"
}
}
kotlinでは、constはプリミティブ型のみを保持できます。関数を渡したい場合は、@ JvmFieldアノテーションを追加する必要があります。コンパイル時に、静的な最終的なパブリック変数として変換されます。ただし、プリミティブ型よりも遅くなります。それを避けるようにしてください。
@JvmField val foo = Foo()
コンパイル時にわかっている値は、定数としてマークすることができます(私の意見ではそうする必要があります)。
命名規則はJavaの規則に従う必要があり、Javaコードから使用したときに適切に表示される必要があります(コンパニオンオブジェクトを使用して達成するのは難しいですが、とにかく)。
適切な定数宣言は次のとおりです。
const val MY_CONST = "something"
const val MY_INT = 1
Naming conventions should follow Java ones
- なぜ?
If in doubt, default to the Java Coding Conventions
Kotlinで定数を宣言するために、クラス、オブジェクト、またはコンパニオンオブジェクトは必要ありません。すべての定数を保持するファイル(たとえば、Constants.ktまたは既存のKotlinファイル内に置くこともできます)を宣言して、ファイル内で定数を直接宣言することができます。コンパイル時に既知の定数は、でマークする必要がありますconst
。
したがって、この場合は次のようになります。
const val MY_CONST = "something"
次に、次のコマンドを使用して定数をインポートできます。
import package_name.MY_CONST
このリンクを参照できます
const val valName = valValue
クラス名の前に置くと、このようにして
public static final YourClass.Kt
それにはpublic static final
値があります。
コトリン:
const val MY_CONST0 = 0
const val MY_CONST1 = 1
data class MyClass(var some: String)
逆コンパイルされたJava:
public final class MyClassKt {
public static final int MY_CONST0 = 0;
public static final int MY_CONST1 = 1;
}
// rest of MyClass.java
class Myclass {
companion object {
const val MYCONSTANT = 479
}
const
キーワードを使用@JvmField
するか、Javaの静的な最終定数にするを使用するか、2つの選択肢があります。
class Myclass {
companion object {
@JvmField val MYCONSTANT = 479
}
@JvmField
アノテーションを使用すると、コンパイル後に定数がJavaで呼び出す方法と同じように挿入されます。
Javaで呼び出すのと同じように、コードでコンパニオン定数を呼び出すと、コンパイラーによって置き換えられます。
ただし、constキーワードを使用すると、定数の値がインライン化されます。インラインとは、コンパイル後に実際の値が使用されることを意味します。
ここで要約すると、コンパイラがあなたのために何をするかです:
//so for @JvmField:
Foo var1 = Constants.FOO;
//and for const:
Foo var1 = 479
Kotlin静的および定数値とメソッド宣言
object MyConstant {
@JvmField // for access in java code
val PI: Double = 3.14
@JvmStatic // JvmStatic annotation for access in java code
fun sumValue(v1: Int, v2: Int): Int {
return v1 + v2
}
}
どこからでも値にアクセス
val value = MyConstant.PI
val value = MyConstant.sumValue(10,5)
と同様にval
、const
キーワードで定義された変数は不変です。ここでの違いはconst
、コンパイル時に既知である変数に使用されることです。
変数の宣言は、Javaでconst
のstatic
キーワードの使用とよく似ています。
Kotlinでconst変数を宣言する方法を見てみましょう。
const val COMMUNITY_NAME = "wiki"
そして、Javaで書かれた類似のコードは次のようになります:
final static String COMMUNITY_NAME = "wiki";
上記の回答に追加-
@JvmField
このプロパティのゲッター/セッターを生成せず、フィールドとして公開しないようにKotlinコンパイラーに指示するために使用されます。
@JvmField
val COMMUNITY_NAME: "Wiki"
静的フィールド
名前付きオブジェクトまたはコンパニオンオブジェクトで宣言されたKotlinプロパティには、その名前付きオブジェクトまたはコンパニオンオブジェクトを含むクラスのいずれかに静的バッキングフィールドがあります。
通常、これらのフィールドはプライベートですが、次のいずれかの方法で公開できます。
@JvmField
注釈;lateinit
修飾子;const
修飾子。詳細はこちら-https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#instance-fields
どの回答にも記載されていないものは、を使用することによるオーバーヘッドですcompanion objects
。ここで読むことができるように、コンパニオンオブジェクトは実際にはオブジェクトであり、それらを作成するとリソースが消費されます。さらに、定数を使用するたびに、複数のゲッター関数を実行する必要がある場合があります。必要なのがいくつかのプリミティブ定数だけである場合はval
、パフォーマンスを向上させ、を回避するために使用するほうがよいでしょうcompanion object
。
TL; DR; 記事の:
コンパニオンオブジェクトを使用すると、実際にはこのコードが有効になります
class MyClass {
companion object {
private val TAG = "TAG"
}
fun helloWorld() {
println(TAG)
}
}
このコードに:
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));
}
}
したがって、それらを避けてください。
ローカル定数:
const val NAME = "name"
グローバル定数:
object MyConstants{
val NAME = "name"
val ID = "_id"
var EMAIL = "email"
}
MyConstants.NAMEにアクセス
Kotlinで定数を定義する方法はいくつかありますが、
コンパニオンオブジェクトの使用
companion object {
const val ITEM1 = "item1"
const val ITEM2 = "item2"
}
上記のコンパニオンオブジェクトブロックを任意のクラス内で使用し、このブロック自体の内部にすべてのフィールドを定義できます。しかし、このアプローチには問題がある、とドキュメントは言う、
コンパニオンオブジェクトのメンバーは他の言語では静的メンバーのように見えますが、実行時には、それらは実際のオブジェクトのインスタンスメンバーであり、たとえば、インターフェイスを実装できます。
コンパニオンオブジェクトを使用して定数を作成し、逆コンパイルされたバイトコードを確認すると、以下のようになります。
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;
}
}
ここから、ドキュメンテーションの内容を簡単に確認できます。コンパニオンオブジェクトのメンバーは他の言語では静的メンバーのように見えますが、実行時にはそれらは実際のオブジェクトのインスタンスメンバーのままです必要以上に余分な作業を行っています。
ここで、以下のようなコンパニオンオブジェクトを使用する必要がない別の方法が登場します。
object ApiConstants {
val ITEM1: String = "item1"
}
ここでも、上記のスニペットのバイトコードの逆コンパイルバージョンを確認すると、次のようになります。
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";
}
}
上記の逆コンパイルされたコードが表示されている場合は、各変数のgetメソッドを作成しています。このgetメソッドはまったく必要ありません。
これらのgetメソッドを取り除くには、以下のようにvalの前にconstを使用する必要があります。
object ApiConstants {
const val ITEM1: String = "item1"
}
上記のスニペットの逆コンパイルされたコードが表示された場合は、コードのバックグラウンド変換が最も少ないため、読みやすくなります。
public final class ApiConstants {
public static final String ITEM1 = "item1";
public static final ApiConstants INSTANCE;
private ApiConstants() {
}
static {
ApiConstants var0 = new ApiConstants();
INSTANCE = var0;
}
}
したがって、これは定数を作成するための最良の方法です。
プリミティブと文字列の場合:
/** The empty String. */
const val EMPTY_STRING = ""
その他の場合:
/** The empty array of Strings. */
@JvmField val EMPTY_STRING_ARRAY = arrayOfNulls<String>(0)
例:
/*
* 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!"
}
}
}
public static final
Javaのフィールドに対応するものが必要な場合const val
は、コンパニオンオブジェクトで使用します。あなたがしたい場合はprivate static final
、フィールドや公共ゲッターを使用しval
、あなたのコンパニオンオブジェクトに。