Imagine I had an interface like:
interface MyInterface {
fun doSomething()
}
And I was interop-ing between Kotlin and Java. I now want a constant static instance of this interface but I want that to be part of the interface. I could do this:
interface MyInterface {
fun doSomething()
companion object {
val CONSTANT = object: MyInterface {
override fun doSomething() { ... }
}
}
}
but that means I need to write MyInterface.Companion.getCONSTANT(). #JvmField doesn't work here.
I've also tried:
interface MyInterface {
fun doSomething()
object CONSTANT: MyInterface {
override fun doSomething() { ... }
}
}
}
Which works in other Kotlin files (I can write MyInterface.CONSTANT) but I'd have to write MyInterface.CONSTANT.INSTANCE in Java. This solution seems the closest to what I want.
Any solutions? I want to be able to write MyInterface.CONSTANT in both Kotlin and Java and have them refer to a single static final object that implements the interface.
I believe I could also convert my Interface to an abstract class but that's the last resort.
The issue of not being able to use #JvmStatic in interfaces is tracked in this ticket: https://youtrack.jetbrains.com/oauth?state=%2Fissue%2FKT-6301
It is fixed by now and one comment says
Fix would be avaliable in 1.2.30 under '-language-version 1.3' option
Related
In the below, since T is reified, I want to use it "almost as if it were a normal class" by accessing its companion object.
class Cls {
companion object {
fun method() { }
}
}
inline fun <reified T> func() {
T.method() // error
}
fun main() {
func<Cls>()
}
But fails with
Type parameter 'T' cannot have or inherit a companion object, so it cannot be on the left hand side of dot
So it seems that a significant amount of information is lost. I get the same error with and without reified. I was hoping a reified type parameter would a fuller generic implementation than Java's. I have a ton of experience in C++ templates.
I've found some workarounds (that are all pretty disappointing using reflection), but really I'm asking why this can't work.
I'm not sure this is answering all the questions, but it's too big for a comment.
First and as stated in the comments, the way the code is written, T is not necessarily a Cls so to allow this you'd need some changes:
open class Cls {
companion object {
fun method() { }
}
}
inline fun <reified T : Cls> func() {
}
open the class and let Kotlin know T is a Cls
However, even though it's inlined, this still wouldn't let you call the companion method because T has no companion. Even without generics:
open class Cls {
companion object {
fun method() { }
}
}
class Foo : Cls
fun main() = Foo.method() // doesn't work
Doesn't work because companions are not inherited. Why? It was a conscious decision by the Kotlin designers. As you know Kotlin aims to correct a lot of issues Java had and this was one.
Static methods in Java are bound at compile-time while overriding is based on dynamic binding at runtime. This becomes quite confusing when you mix both and Kotlin tried to avoid this. Here's an example:
class Cls {
public static void method() {
System.out.println("Cls' method");
}
}
class Foo extends Cls {
public static void method() {
System.out.println("Foo's method");
}
}
public class Main {
public static void main(String[] args) {
Cls parent = new Foo();
parent.method();
}
}
If method would truly be overridden it would print out Foo's method, but indeed this prints Cls' method. The reason is that there's no overriding, but there's shadowing happening. On the other hand, if the methods wouldn't be static, then you'd get Foo's method since it is indeed overridden. This apparently caused confusion amongst developers and Kotlin completely disallowed it.
I'm new to programming in Kotlin and I've already managed to run into the classic circular dependency issue - I know Kotlin can cope with those but I'd like to know how would I go about changing my design to avoid it. What structures or Kotlin functionality should I use in the following?
import MyClass
interface MyInterface {
fun useMyClass(myInstance: MyClass)
}
import MyInterface
class MyClass(myList: List<MyInterface>) {
val storedList: List<MyInterface> = myList
var myValue: Int = 10
}
I would like MyClass to store multiple objects which implement MyInterface, but I would also like each of those objects to reference the class they have been passed to, i.e. each call of useMyClass would have the signature of useMyClass(this).
For example, I could create a class
class ImplementingMyInterfaceClass(): MyInterface {
override fun useMyClass(myInstance: MyClass) {
myInstance.myValue += 10
}
}
and call it somewhere within MyClass:
ImplementingMyInterfaceClass().useMyClass(this)
Technically I could create another construct in the middle which would be used by MyInterface and inherited/implemented by MyClass, but this just doesn't feel correct. Any suggestions?
Note: In my specific issue, it might be helpful to consider each implementation of MyInterface as a sort of a "modifier" (since it will modify the instance of the class) - MyClass instances should be aware of its modifiers and each modifier should be able to modify that instance.
It's going to largely depend on what the interface has to do, but you could limit its function argument to some interface that MyClass implements:
interface MyInterface {
fun increaseSomeValue(someValueHolder: MySubInterface)
interface MySubInterface {
var myValue: Int
}
}
class MyClass(myList: List<MyInterface>): MyInterface.MySubInterface {
val storedList: List<myInterface> = myList
override var myValue: Int = 10
}
Or your interface can take a property argument:
interface MyInterface {
fun increaseSomeValue(someValue: KMutableProperty<Int>)
}
class MyInterfaceImpl: MyInterface {
override fun increaseSomeValue(someValue: KMutableProperty<Int>) {
someValue.setter.call(someValue.getter.call() + 10)
}
}
// from MyClass:
storedList.first().printSomeValue(::myValue)
In other cases where we don't need to both get and set, it could be cleaner to take a more versatile function argument (lambdas could be passed):
interface MyInterface {
fun printSomeValue(valueProvider: () -> Int)
}
class MyInterfaceImpl: MyInterface {
override fun printSomeValue(valueProvider: () -> Int) {
println(valueProvider())
}
}
// from MyClass:
storedList.first().printSomeValue(::myValue)
// or
storedList.first().printSomeValue { 1..10.random() }
My question might be noob but please help me. I don't understand what is purpose of not allowing non-open classes with "is" keyword in kotlin.
Sample code 1
fun main(){
val randomclassobject = RandomClass()
println(randomclassobject is someRandomInterface)
}
open class RandomClass{
}
interface someRandomInterface{
fun mustImplementThis()
}
The above code works perfectly fine
Now
Sample code 2
fun main(){
val randomclassobject = RandomClass()
println(randomclassobject is someRandomInterface)
}
class RandomClass{
}
interface someRandomInterface{
fun mustImplementThis()
}
without open keyword it shows the error "Error:(3, 34) Kotlin: Incompatible types: someRandomInterface and RandomClass"
Why open keyword really matters?
When you write it like this
class RandomClass {
}
interface SomeRandomInterface {
fun mustImplementThis()
}
It is not possible for any object to be an instance of both RandomClass and SomeRandomInterface because RandomClass itself does not implement SomeRandomInterface and it cannot have any subclasses that implement it either because it is not open (Kotlin classes by default cannot be extended unless you add open).
Since the compiler knows that this check cannot return true, it marks it as an error. Most other languages would probably just warn you that the check is useless, but Kotlin makes it illegal entirely.
On the other hand, when you write
open class RandomClass {
}
interface SomeRandomInterface {
fun mustImplementThis()
}
even though the class itself does not implement the interface, it could have a subclass that implements it, for example
open class RandomClass {
}
interface SomeRandomInterface {
fun mustImplementThis()
}
class RandomSubClass : RandomClass(), SomeRandomInterface {
fun mustImplementThis() {}
}
which means that the check can return true, so the compiler allows it in that case.
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
With the code below, I am getting the following error in IntelliJ IDEA 13.1.6 and Kotlin plugin 0.11.91.AndroidStudio.3:
Platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;):
• public open fun getName(): kotlin.String?
• internal final fun <get-name>(): kotlin.String?
Java class, JavaInterface.java:
public interface JavaInterface {
public String getName();
}
Kotlin class, KotlinClass.kt
public class KotlinClass(val name: String?) : JavaInterface
I've tried overriding the 'getter' method by
adding override fun getName(): String? = name, but that produces the same error.
I can see one workaround by doing this instead:
public class KotlinClass(val namePrivate: String?) : JavaInterface {
override fun getName(): String? = namePrivate
}
But in my real-world case I have a number of properties to implement and need setters too. Doing this for each property doesn't seem very Kotlin-ish. What am I missing?
Making that variable private solves the problem.
public class KotlinClass(private val name: String?) : JavaInterface
You could use #JvmField for instructs the compiler not generate getter/setter, and you can implement your setters and getters. With this your code work well in Java (as attribute getter/setter) and Kotlin as property
Example:
JAVA:
public interface Identifiable<ID extends Serializable>
{
ID getId();
}
KOTLIN:
class IdentifiableImpl(#JvmField var id: String) :Identifiable<String>
{
override fun getId(): String
{
TODO("not implemented")
}
}
The annotation feature of Kotlin named #JvmName will solve the duplication problem in Java and Kotlin when having the same signature.
fun function(p: String) {
// ...
}
// Signature: function(Ljava/lang/String)
With the use of JvmName will be:
#JvmName("functionOfKotlin")
fun function(p: String) {
// ...
}
// Signature: functionOfKotlin(Ljava/lang/String)
IMHO most readable combination is field + explicit interface implementation by the single-expression function (combination of #Renato Garcia's and #Steven Spungin's answers):
Java:
public inteface SomeInterface {
String getFoo();
}
Kotlin:
class Implementation(#JvmField val foo: String) : SomeInterface {
override fun getFoo() = foo
}
Another work-around is to declare the properties in an abstract Kotlin class, then write a small java class that extends KotlinClass and implements JavaInterface.
// JavaInterface.java
public interface JavaInterface {
int getFoo();
void setFoo(int value);
}
// KotlinClass.kt
abstract class KotlinClass(open var foo : Int = 0) {
}
// JavaAdapter.java
class JavaAdapter extends KotlinClass implements JavaInterface {
// all code in KotlinClass, but can't implement JavaInterface there
// because kotlin properties cannot override java methods.
}
We have found that to use the same names without clashing, the ctor args must be private AND you must still override the interfaces methods. You don't need any additional backing fields. Also, your expression body assignment will not recurse, so you can safely use that syntax.
Java Interface
interface IUser {
String getUserScope();
String getUserId();
}
Kotlin Class
class SampleUser(private val userScope: String, private val userId: String) : IUser {
override fun getUserId() = userId
override fun getUserScope() = userScope
}
If you have direct control over the interface then the best approach is to write the interface in Kotlin. You can then write your class
public class KotlinClass(override val name: String?) : KotlinInterface
and still reference it from any Java code using the same interface as before. This looks a lot neater than setting all the properties to private and overriding the get function. Obviously if you can't migrate the interface to Java because you don't own it then that seems to be the only solution.
public interface JavaInterface {
public String getName();
}
public class KotlinClass(val namePrivate: String?) : JavaInterface {
private var name = namePrivate
override fun getName(): String? {
return name
}
}
Rename the variable to something else, or make it private if u dont want it to be public.
convert function to property instead of initializing property from a function.
for ex:
fun getCountriesList(): List<Country> {
val countries = mutableListOf<Country>()
countries.add(Country("in", "+91", "India", R.drawable.indian_flag))
countries.add(Country("us", "+1", "United States",R.drawable.us_flag))
return countries
}
to
val countriesList: List<Country>
get() {
val countries = mutableListOf<Country>()
countries.add(Country("in", "+91", "India", R.drawable.indian_flag))
countries.add(Country("us", "+1", "United States", R.drawable.us_flag))
return countries
}