This question already has answers here:
Kotlin calling non final function in constructor works
(3 answers)
Closed 1 year ago.
I have a (more complex) version of these 4 classes the problem is when I try to initialize Test() android studio tells me cannot call data.log() on a null object reference. Why is this? how can i fix it?
abstract class Test() {
protected abstract val data: CustomClass
init {
data.log()
}
}
class myClass(): Test() {
override val data = Hello()
}
abstract class CustomClass() {
function log() {
Log.i("TEST", "HELLO");
}
}
class Hello(): CustomClass() {
}
I have a lot of classes that extend Test() and Hello() I do not want to have to call data.log() in multiple classes to avoid repeating code
Try to evaluate your code step by step:
invoke myClass() -> myClass constructor called from your code
invoke Test() -> parent constructor called from myClass constructor
invoke Test's init -> init section called from Test constructor
NPE -> data field is not initialized yet
As you can see, the init section is called BEFORE the data is initialized. Solution to your problem is pretty simple, move the data field right into the Test's constructor and remove the abstract modifier:
abstract class Test(protected val data: CustomClass) {
init {
data.log()
}
}
class myClass(): Test(Hello())
P.S.: I hope this is just an example and you don't start your class names with lowercase. :)
Related
Im kinda new to Kotlin and I was wondering how I could make a static method.
Test.foo() //I want to do this from somewhere else in the program
open class Test() {
private giorgor: String? = null
fun foo(value:String) {
giorgor = value
}
}
I need to change the value of giorgor from somewhere else in the code and I thought I could use a static method to do that but I dont know how. Test also needs to be an open class
The equivalent of a static method in Kotlin is a method in the companion object, e.g.:
class Test() {
// …
companion object {
fun foo() = // …
}
}
You can access it in the obvious way:
fun main() {
Test.foo()
}
However, the bits of code I've elided make me suspect that this isn't exactly what you want: your example has foo() referring to a property of Test — and because each instance of Test has its own version of that property, it would need to refer to an specific instance. (And if you had an instance, there would be no need of the companion class — you could just make it a regular method of Test.)
In a comment, you refer to a Minecraft plug-in — can you explain what requirements that has?
BTW, a simpler alternative to the companion object is just a top-level method:
fun foo() = // …
From the same file, you can call it as foo(); from elsewhere, you'd call it as <Filename>Kt.foo() (since the compiler generates a dummy classname for top-level functions and properties, based on the filename). However, the same issues apply to that too.
If I'm understanding you correctly, you want an object instead of a class
object Test {
var giorgor: String = "jiorgor"
fun foo() = println(giorgor)
}
fun main() {
Test.foo()
}
One way to do this is by making the class open or abstract and adding this
companion object Default: Test()
This makes it act like every method of Test() is inside the companion object Default.
If you wanted, you could also override an open method and make it have a different output for when it is used statically:
fun main() {
val test = Test()
test.foo() //Output: "jiorgor"
Test.foo() //Output: "static jiorgor"
}
public open class Test() {
var giorgor: String = "jiorgor"
open fun foo() = println(giorgor)
companion object Default : Test() {
override fun foo() = println("static jiorgor")
}
}
I have the following interface (SAM):
fun interface WebResponseHandler
{
fun onWebResponseFinished(jsonString:String?)
}
and Inside a class, (lets call the class ClassA) i wrote the following code:
private val onInitWebResponseHandler: VolleyHandler.WebResponseHandler = VolleyHandler.WebResponseHandler()
{
Thread(ParseJsonStringOnInit(WeakReference(this),
weakRefIOnAllScoresDataFirstFetched, it)).start()
}
i can't understand why in the first argument of ParseJsonStringOnInit, this is considered as ClassA and not as VolleyHandler.WebResponseHandler?
Is this a convention when using SAM?
In the following code I would like to set a reference to the class instance so that static functions can return a reference to it:
open class TestRunner {
init {
instance = this
}
companion object {
private lateinit var instance: TestRunner
fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner {
for (setup in testSetups) {
testsSetups.add(setup)
}
return instance
}
}
}
But setting instance = this is not allowed. How can I return an instance of the class from a function while keeping the class as a singleton?
If I get you right, you want something like this:
abstract class TestRunner {
companion object : TestRunner()
}
This seems to work. Instead of keeping a variable that holds a reference to the class, simply referencing the name of the class is sufficient. However, to return an instance of the class from functions, the return type must be Companion:
open class TestRunner {
companion object {
fun addTestSetups(vararg testSetups: () -> TestSetup): Companion {
for (setup in testSetups) {
testsSetups.add(setup)
}
return TestRunner
}
}
}
This is not a true singleton because you can still create a new instance if you did this:
val testRunner = TestRunner()
However, if you never create an instance but only refer to the functions statically, it does behave like a singleton and the state of any private variables inside the companion object will still be maintained.
Update:
I came across this code on the Android developer site that shows an example of a class that is setup as a singleton:
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager: StockManager = StockManager(symbol)
private val listener = { price: BigDecimal ->
value = price
}
override fun onActive() {
stockManager.requestPriceUpdates(listener)
}
override fun onInactive() {
stockManager.removeUpdates(listener)
}
companion object {
private lateinit var sInstance: StockLiveData
#MainThread
fun get(symbol: String): StockLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
return sInstance
}
}
}
But it should be pointed out that this example requires functions that need to return an instance to first check if the instance variable is set and if not, create a new instance. I'm not sure what the point of that is since to call the function you already have an instance. So why bother create a new instance? Doesn't seem to make any sense.
object in Kotlin is the singleton, not the class its defined within. A companion object has the extra convenience of allowing you to call it by the name of that outer class. But it otherwise shares no hierarchy with it.
To make your class subclassable, you can't define the functions in the companion object. But you can make the class abstract so it can't be instantiated unless subclassed. Then make your companion object extend the abstract class so it will have all those functions available.
abstract class TestRunner{
open fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner{
//...
return this
}
companion object: TestRunner()
}
Usage:
TestRunner.addTestSetups(someTestSetup)
Note that your singleton is not an instance of TestRunner. It is a singleton instance of a subclass of TestRunner. But since you define no extra functions and override nothing, it behaves exactly like a TestRunner.
If you want a subclass:
abstract class ExtendedTestRunner: TestRunner() {
fun someOtherFunction() {}
companion object: ExtendedTestRunner()
}
The companions are not being subclassed, but their abstract parents can be.
This question already has answers here:
Utils class in Kotlin
(3 answers)
Closed 1 year ago.
I was playing with Kotlin, and creating Util class with different ways. I am approaching a way that works best for calling by either Kotlin or Java.
Now I have created many types of Util. And now I am very confused which is best to use and most important why? I am finding best way considering Heap, Memory, Performance.
My question may look stupid for you guys, but I am in maze and can't come to a solution myself.
Here is my playground.
I have created 5 Kotlin files. in which I have put foo() method. and tried to call by Kotlin and Java.
Calling class Bar.kt
class Bar {
fun bazz() {
UtilClass.instance.foo()
UtilClassObject.UtilClassObject.foo()
UtilCompanionObject.foo()
UtilFileObject.foo()
foo() // from UtilFile
}
}
Calling class Qux.java
public class Qux {
public void bazz() {
UtilClass.Companion.getInstance().foo();
UtilClassObject.UtilClassObject.INSTANCE.foo();
UtilFileKt.foo();
UtilFileObject.INSTANCE.foo();
UtilCompanionObject.Companion.foo();
}
}
And here is the maze that makes me confused to choose best.
UtilClass.kt
class UtilClass {
fun foo() { ... }
companion object {
val instance = UtilClass()
}
}
UtilClassObject.kt
class UtilClassObject {
object UtilClassObject {
fun foo() { ... }
}
}
UtilCompanionObject.kt
class UtilCompanionObject {
companion object {
fun foo() { ... }
}
}
UtilFile.kt
fun foo(){ ... }
UtilFileObject.kt
object UtilFileObject {
fun foo() { ... }
}
It may take to answer my question and explaining it well. So I really appreciate your efforts in advance.
All options are present on the Kotlin reference page for interop between Kotlin and Java: https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html
Your options to call from Java something on class MyUtil and call it without an instance such as MyUtil.foo() then you would simply do one of the two options:
// smallest byte code,
// static invocation of foo() from Kotlin side,
// also static call from Java to foo()
object MyUtil {
#JvmStatic fun foo() { ... }
}
or
// creates two classes,
// static lookup of companion followed by virtual call on that instance to foo() from Kotlin,
// Java is a static call to foo()
class MyUtil {
companion object {
#JvmStatic fun foo() { ... }
}
}
And you would call it the same from Kotlin MyUtil.foo(). This is specifically the model of making a Kotlin method static.
Both examples look the same from Java in that they are just direct static calls to a static method. From Kotlin the first example is a static call as well, the second looks up an instance of the companion first and then does a virtual call on the method. The Second example creates two classes, the other only creates a single class.
The other options you present are not more efficient and are uglier syntax. Based on smallest byte code, fewest classes, and fastest performance pick the first example that is 1 class only and all static calls.
How to use method references to refer to super class methods?
In Java 8 you can do SubClass.super::method.
What would be the syntax in Kotlin?
Looking forward to your response!
Conclusion
Thanks to Bernard Rocha!
The syntax is SubClass::method.
But be careful. In my case the subclass was a generic class. Don't forget to declare it as those:
MySubMap<K, V>::method.
EDIT
It still doesn't work in Kotlin.
Hers's an example in Java 8 of a method reference to a super class method:
public abstract class SuperClass {
void method() {
System.out.println("superclass method()");
}
}
public class SubClass extends SuperClass {
#Override
void method() {
Runnable superMethodL = () -> super.method();
Runnable superMethodMR = SubClass.super::method;
}
}
I'm still not able to do the same in Kotlin...
EDIT
This is an example how I tried to achieve it in Kotlin:
open class Bar {
open fun getString(): String = "Hello"
}
class Foo : Bar() {
fun testFunction(action: () -> String): String = action()
override fun getString(): String {
//this will throw an StackOverflow error, since it will continuously call 'Foo.getString()'
return testFunction(this::getString)
}
}
I want to have something like that:
...
override fun getString(): String {
//this should call 'Bar.getString' only once. No StackOverflow error should happen.
return testFunction(super::getString)
}
...
Conclusion
It's not possible to do so in Kotlin yet.
I submitted a feature report. It can be found here: KT-21103 Method Reference to Super Class Method
As the documentation says you use it like in java:
If we need to use a member of a class, or an extension function, it
needs to be qualified. e.g. String::toCharArray gives us an extension
function for type String: String.() -> CharArray.
EDIT
I think you can achieve what you want doing something like this:
open class SuperClass {
companion object {
fun getMyString(): String {
return "Hello"
}
}
}
class SubClass : SuperClass() {
fun getMyAwesomeString(): String {
val reference = SuperClass.Companion
return testFunction(reference::getMyString)
}
private fun testFunction(s: KFunction0<String>): String {
return s.invoke()
}
}
Don't know if it is possible to get the reference to super class's function, but here is an alternative to what you want to achieve:
override fun getString(): String = testFunction { super.getString() }
According to Bernardo's answer, you might have something like this. It doesn't have remarkable changes.
fun methodInActivity() {
runOnUiThread(this::config)
}
fun config(){
}
What is more, in the incoming 1.2 version you can use just
::config