Kotlinでは、どのクラスからでもインスタンスを経由せずにアクセスできるメソッド(クラスメソッド)を作る方法の1つに「companion object」というものがあります。
例えば、こんな感じでcompanion objectの中にnewInstanceメソッドを設定すると、
class KotlinFragment : Fragment() { ******** companion object { //↓これ fun newInstance(param1: String, param2: String) = KotlinFragment().apply { arguments = Bundle().apply { putString(ARG_PARAM1, param1) putString(ARG_PARAM2, param2) } } } }
他のKotlinファイルから呼び指す際に、KotlinFragmentのインスタンスを経由せずに、こんな感じでアクセスすることが出来ます。
もくじ
companion object内に作ったメソッドはJavaでいう「static」メソッドではない
まさに、これはJavaでいう「staticメソッド(クラスメソッド)」という感じになるはずなのですが、ところがどっこいしょ。
他のJavaファイルからは、上のような感じで呼び出すことができず、
Companionクラスを経由しないと呼び出すことができないのです。
なんでや?
Kotlinのcompanion object内のメンバ(プロパティ・メソッド)は、一見Javaのstaticのように見えますが、実行時にインスタンス化されるので、インターフェースの実装なども出来るという点で、「static」とは異なる。
ということらしいです(companion objectは実際のオブジェクトのシングルトンインスタンスだそうです)。
こんな感じで。
interface Factory<T> { fun create(): T } class MyClass { companion object : Factory<MyClass> { ← Factoryインターフェースを実装している override fun create(): MyClass = MyClass() } }
Note that, even though the members of companion objects look like static members in other languages, at runtime those are still instance members of real objects, and can, for example, implement interfaces:
(companion object内のメンバ(プロパティ・メソッド)は、他のプログラミング言語(Java等)における『static(静的な)』メンバのように見えるが、Kotlinでは、実行時におけるこれらのメンバは実オブジェクトのインタンスメンバ(動的メンバ)であり、たとえばインターフェースを実装することもできる)
https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects
ほなどないしたらエエねん!?
「@JvmStatic」アノテーションをつけたらエエということらしいです。
However, on the JVM you can have members of companion objects generated as real static methods and fields, if you use the
@JvmStatic
annotation.(しかしながら、JVM(Java Virtual Machine)では、companion objectのメンバを本当にstaticなフィールドやメソッド(メンバ)として生成することもでき、その際は@JvmStaticアノテーションをつければよい)
https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects
ですので、こうしてやると、
class KotlinFragment : Fragment() { ******** companion object { @JvmStatic //←こいつ fun newInstance(param1: String, param2: String) = KotlinFragment().apply { arguments = Bundle().apply { putString(ARG_PARAM1, param1) putString(ARG_PARAM2, param2) } } } }
Javaファイルからでも、ちゃんとstaticメソッドとしてアクセスできるようになりました。
ということです。
詳しい解説は下の動画をご覧ください。それよりもっと詳しく知りたい場合はこれを読めばいいかもです。