Access Parent class variables in companion Object in Kotlin - android

I am trying to call static function of one class in other like java , But in kotlin I can not make a static function , and I have to make a companion object in which I have to define my function , But while doing this I am not able to access parent class variables , is there any way I can achieve this in kotlin .
class One {
val abcList = ArrayList<String>()
companion object {
fun returnString() {
println(abcList[0]) // not able to access abcList here
}
}
}
class Two {
fun tryPrint() {
One.returnString()
}
}
// In Java we can do it like this
class One {
private static ArrayList<String> abcList = new ArrayList<>();
public void tryPrint() {
// assume list is not empty
for(String ab : abcList) {
System.out.println(ab);
}
}
public static void printOnDemand() {
System.out.println(abcList.get(0));
}
}
class Two {
public void tryPrint(){
One.printOnDemand();
}
}
I want to access fun returnString() like static function of class one like we do in java , if any one have achieved this please help .

In your case abcList is a member variable of the class. Each instance of a class has their own version of its member variables which means that a static method cannot access them. If you want to access it from your companion object it has to be static too.
class One {
companion object {
val abcList = ArrayList<String>()
fun returnString() {
println(abcList[0])
}
}
}
class Two {
fun tryPrint() {
One.returnString()
}
}
This code will work, but keep in mind that in this case there will be only one instance of abcList. Accessing a member variable from a static function is not possible (not even in Java).
Here's the Kotlin version of your Java example:
class One {
companion object {
val abcList = ArrayList<String>()
fun printOnDemand() {
println(abcList[0])
}
}
fun tryPrint() {
for (ab in abcList) {
println(ab)
}
}
}
class Two {
fun tryPrint() {
One.printOnDemand()
}
}

Rule: You can't access static properties, members of a class in none static members and you can't access none static properties, members of a class in static members which is the companion object class.
This rule is in both Java and Kotlin. If you want to access a none static member of a class
inside static members you have to declare it inside companion object class.

Use the following code for you case.
object One {
val abcList: MutableList<String> = mutableListOf()
fun returnString() {
println(abcList[0])
}
fun printOnDemand() {
println(abcList[0]);
}
}
class Two {
fun tryPrint() {
One.printOnDemand()
}
}

Related

Singleton class in Kotlin with init

I just to wish clarify some methodology using singletons in Kotlin.
I have this class:
class TestClass {
companion object {
val instance = TestClass()
fun runSync2() {
Log.d("TAG", "Running sync2")
}
init {
Log.d("TAG", "Init companion")
}
}
init {
Log.d("TAG", "Init class")
}
fun runSync1() {
Log.d("TAG", "Running sync1")
}
}
And this test functions:
1. TestClass.instance.runSync1()
2. TestClass.runSync2()
3. TestClass().runSync1()
When calling function 1 twice, init inside companion object will be called once. So only one instance of TestClass is created and run runSync1() twice, correct?
When calling function 2 twice, init inside companion object will be called once. So only one instance of TestClass is created and run runSync2() twice, correct? So what is the difference between 1 and 2?
When calling function 2 twice, 2 instances of TestClass crated, 2 init inside class will run and 2 runSync1 will run independently?
Can you please provide more clarification and correct the wrong parts?
When understanding the companion objects one thing to remember is that
A companion object is initialized when the corresponding class is loaded (resolved) that matches the semantics of a Java static initializer.
So the init block inside the companion object will be executed only once, when the TestClass is being loaded, same goes with the property named instance, it will be assigned an object of TestClass only once at class load time.
To better understand this you can look at your code converted to java, which will look something like
public final class TestClass {
// Property of companion object and the init block are now part of TestClass
private static final TestClass instance = new TestClass();
static {
Log.d("TAG", "Init companion");
}
public static final TestClass.Companion Companion = new TestClass.Companion((DefaultConstructorMarker)null);
public final void runSync1() {
Log.d("TAG", "Running sync1");
}
public TestClass() {
Log.d("TAG", "Init class");
}
public static final class Companion {
public final TestClass getInstance() {
return TestClass.instance;
}
public final void runSync2() {
Log.d("TAG", "Running sync2");
}
private Companion() { }
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}

Define common functions in kotlin

For define Util(common functions) we can use 3 approach :
First :
We can define a File and add function to it like this :
fun func1(): String {
return "x"
}
fun func2(): String {
return "y"
}
Then we can use this in every where like this :
fileName.func1()
Second :
We can define a class and add these functions to class like this :
class Util{
fun func1(): String {
return "x"
}
fun func2(): String {
return "y"
}
}
we can inject it and use this like :
private val mUtil: Util by inject()
mutil.func1()
Third:
We can define an object like this :
object Util{
fun func1(): String {
return "x"
}
fun func2(): String {
return "y"
}
Then we can use this like :
Util.func1()
suppose that we have reusable fun that it use in different class , activity or fragment now is better to use first , second or third ?
According to my understanding :
In the first example, we simply define a function to be used within the scope of component (could be a fragment or an activity ..)
In the second example, which I think more used in Java than Kotlin, you simply create a class in which you define some static variable or function to be accessed in your components later
Example 3, I have no idea as I never used that
first one is static function
second one is normal function
third is singleton function
you can decomplie to see the java code and see their differs.
Kotlin file
fun fun1() {}
class TestClass {
fun testFun() {}
}
object ObjectClass {
fun objectFun() {}
}
Java file
public final class TTTKt {
public static final void fun1() {
}
}
public final class TestClass {
public final void testFun() {
}
}
public final class ObjectClass {
public static final ObjectClass INSTANCE;
public final void objectFun() {
}
private ObjectClass() {
}
static {
ObjectClass var0 = new ObjectClass();
INSTANCE = var0;
}
}

How i can use context in Singleton?

I need in my Singleton -> Context. I know that I can't passing argument in constructor, because object hasn't constructor.
Then I call it from my Application class.
Here is the code:
object Singleton {
var userAgentInfo: String = UserAgentTools.buildUserAgent(context)
fun initializeSdk() {
AuthenticatorApiManager.initializeSdk(userAgentInfo)
}
}
Move the initialization of userAgentInfo to the initializeSDK method, and send the Context as an argument, make sure to send the ApplicationContext.
object Singleton {
var userAgentInfo: String? = null
fun initializeSdk(context: Context) {
userAgentInfo = UserAgentTools.buildUserAgent(context)
AuthenticatorApiManager.initializeSdk(userAgentInfo)
}
}
Make Application class and write below code.
companion object {
private lateinit var sInstance: ApplicationClass
fun getInstance(): ApplicationClass {
return sInstance
}
}
Use in object like below.
ApplicationClass.getInstance()
You can use context in your Singleton class using Application class instance.here it is

#file:JvmName vs #JvmStatic in companion object

I'm migrating part of application from Java to Kotlin and have a question about that.
What is preferable or better way ?
File with annonation #file:JvmName and funtion inside
#file:JvmName("ClassX")
fun funX() {}
or
Typical class with #JvmStatic annotation inside companion object
class ClassX {
companion object {
#JvmStatic
fun funX() {}
}
}
Let's look at the decompiled code to answer this question.
Kotlin file with a #JvmName annotation like yours:
#file:JvmName("ClassX")
fun funX() {}
will be compiled into a bytecode, analogous to this Java code:
#JvmName(
name = "ClassX"
)
public final class ClassX {
public static final void funX() {
}
}
Pretty similar to what you'd probably write when using Java, right?
A Kotlin class with a companion object like this:
class ClassX {
companion object {
#JvmStatic
fun funX() {}
}
}
is analogous to this Java code:
public final class ClassX {
public static final ClassX.Companion Companion = new ClassX.Companion((DefaultConstructorMarker)null);
#JvmStatic
public static final void funX() {
Companion.funX();
}
public static final class Companion {
#JvmStatic
public final void funX() {
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
As you see, class with a companion object will generate more code.
Is it good or bad? You decide. I'd say it's bad and it's better to use a file with #JvmName annotation. There is also a discussion on Kotlin's forum about this topic: read the best practices.
BTW, you can look at the bytecode and decompiled Java code in IntelliJ IDEA via "Tools" -> "Kotlin" -> "Show Kotlin Bytecode".

"singleton" pattern method best way in kotlin

Can someone help me to find a better way to create a single instance in Kotlin?
class Bar(private val blub) {
private lateinit var foo: FooService
private lateinit var doo: DooService
override fun getFooService(): FooService {
if (!::foo.isInitialized) {
foo = FooService(blub)
}
return foo
}
override fun getDooService(): DooService {
if (!::doo.isInitialized) {
doo = DooService(blub)
}
return doo
}
}
Edit:
I don't want to init every object at beginning - should be only done when needed.
Thanks in advance!
If your FooService doesn't take any parameters via the getter for its initialization, you can use an object for this:
object FooHolder {
val foo: FooService = FooService(...)
}
Otherwise, your pattern seems just fine, the alternative would be to use a nullable variable instead of lateinit, but they're essentially the same:
private var foo: FooService? = null
override fun getService(): FooService {
if (foo == null) {
foo = FooService(...)
}
return foo!!
}
Your class is not looking as singleton. Maybe you want something like this
class Bar(private val blub) {
var foo by lazy{ FooService(blub) }
}
OR you can put it in companion object to have the same instance between all objects

Categories

Resources