Instantiating interfaces in Java/Kotlin - java

I read that in Java "interfaces cannot be instantiated - they can only be implemented by classes or extended by other interfaces".
However I can perfectly write:
val set = setOf<String>("one", "two")
in Kotlin, with set being of type Set<String>.
Doesn't this contradict my first statement as I'm instantiating the Set?

I read that in Java "interfaces cannot be instantiated - they can only be implemented by classes or extended by other interfaces"
What this means is just that you can't write
Set<String> set = new Set<String>(...);
(don't confuse with new Set<String> { ... } which creates an anonymous class implementing Set and instantiates that class). You can write Set.of("one", "two") though this method was only added in Java 9. It is a factory method, just like Kotlin setOf, not "instantiating an interface".
The Kotlin equivalent to the illegal new Set would be
val set = Set<String>(...)
which is also not allowed.
Though Kotlin intentionally blurs the line between constructors and methods; it would be perfectly in line with other types in the standard library to define a factory method called Set which would be called in the same way, or an operator fun invoke in the companion object. See the List method for an example.

Related

How to refer to a Kotlin delegating singleton object from Java?

I have a Kotlin object that delegates it's implementation, in my case to MutableSet<String> like so:
object MySet : MutableSet<String> by TreeSet<String>() {
init {...}
}
In Java I'd like to say something like MySet.contains. How can I do that?
object declares a singleton. Unlike Kotlin, you cannot use a type name to refer to its instance in Java. Therefore, the Kotlin compiler translates the singleton instance to a field called INSTANCE instead, so you can do:
MySet.INSTANCE.contains(foo);
in Java.
While you can probably find INSTANCE by chance, just by using the auto-complete in IntelliJ, the only place where I could find this officially documented is in the Calling Kotlin from Java page at the bottom of this section, which talks about calling static methods.
object Obj {
#JvmStatic fun callStatic() {}
fun callNonStatic() {}
}
In Java:
Obj.callStatic(); // works fine
Obj.callNonStatic(); // error
Obj.INSTANCE.callNonStatic(); // works, a call through the singleton instance
Obj.INSTANCE.callStatic(); // works too

Kotlin default implementations from Java

I have an interface in Kotlin that I want to have default implementations so that implementing classes will only have to implement a subset of the methods. Example:
interface PersonInterface {
val firstname: String?
get() = null
val lastName: String?
get() = null
val phoneNumbers: List<String>?
get() = null
val interests: List<List<String>>?
get() = emptyList()
}
This in my understanding would create default implementations for the methods to return null or an empty list or whatever I would have as defaults in general.
But if I create the following class in Java (which I expected it would compile):
public class Employee implements PersonInterface {
}
I get:
Class Employee must either be declared abstract or implement abstract
method getFirstName in PersonInterface
Is it possible to use default interface implementation defined in Kotlin from Java?
According to documentation (https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html):
Starting from JDK 1.8, interfaces in Java can contain default methods. To make all non-abstract members of Kotlin interfaces default for the Java classes implementing them, compile the Kotlin code with the -Xjvm-default=all compiler option
Note: Prior to Kotlin 1.4, to generate default methods, you could use the #JvmDefault annotation on these methods. Compiling with -Xjvm-default=all in 1.4 generally works as if you annotated all non-abstract methods of interfaces with #JvmDefaultand compiled with -Xjvm-default=enable. However, there are cases when their behavior differs. Detailed information about the changes in default methods generation in Kotlin 1.4 is provided in this post on the Kotlin blog.

Two observables point to the same reference

I wrote the following example and checked the value of the observerA variable for objects a and b.
Example
class Test {
val observerA = Observer<String>{}
}
Check
val a = Test()
val b = Test()
AppLogger.LOGE("[A]ObserverA: ${a.observerA} [B]ObserverA: ${b.observerA}")
Result
[A]ObserverA: com.test.Test$observerA$1#e3d8a1b
[B]ObserverA: com.test.Test$observerA$1#e3d8a1b
My guess is that a.observerA and a.observerA should be different, but they refer to the same object.
When I wrote observerA as below, I saw that different objects were created. I do not know why this difference appears.
val observerA = object : Observer<String>{
override fun onChanged(t: String?) {
}
}
When you use this syntax, you're defining a lambda with an empty body:
Observer<String>{}
This lambda will be compiled down to an anonymous class. If the lambda doesn't capture any variables, as an optimization step, there'll only be one instance of it (since you can't tell the difference in behaviour anyway).
As you've discovered already, you can force the compiler to create new instances of this Observer by using the full object expression syntax, which guarantees a new instance every time.
Source for the statements above, from the Kotlin in Action book:
As of Kotlin 1.0, every lambda expression is compiled into an anonymous class (...). If a lambda captures variables, the anonymous class will have a field for each captured variable, and a new instance of that class will be created for every invocation. Otherwise, a single instance will be created. The name of the class is derived by adding a suffix from the name of the function in which the lambda is declared (...).
If class Test is a singleton which is used in dagger for example (dependency injection) it will only be initialized once and the second time it will take point to the same object.
https://en.wikipedia.org/wiki/Singleton_pattern

Passing parameter information with { }

So you can do generic types with <> and you can pass objects with (). But what is it called when you pass information with {}, as in this example?
new Filter<CLDevice>() {
public boolean accept(CLDevice device) {
CLDeviceCapabilities caps = CLCapabilities.getDeviceCapabilities(device);
return caps.CL_KHR_gl_sharing;
}
}
Also does this work only for constructors or can any method make use of {} to gather data?
Is there any caveats associated with such code, like is it not performant?
What you are showing is not actually passing information (like passing an argument to a method), it's passing behavior.
Because up until Java 7 no lambdas existed, in order to pass behavior you always needed a class (after all in the java world everything a class). The syntax you are showing, is the syntax for an anonymous inner class. This syntax is used as a shortcut when you don't need/want to create a new class file, but just need to pass some behavior.
Note that you could just as easily use the same syntax if you had to implement (behavior passing) more than one method - something you could not do with Java 8 lambdas.
In this case you are providing an implementation via an anonymous class for a Single Abstract Method (SAM) interface or functional interface.
In java { and } define scope. There are various type of scopes for example class, method, block.
In your example your are creating a anonymous class.
So you can do generic types with <>.
You can pass objects with ().
What is it called when you pass information with {}, as in this example
With {} you create a body of a method or an anonymous class/method/object.. here your code is defining an anonymous method.

Is there an elegant way to change what methods/variables an object of a class can use based on the constructor used to create this object?

So for example, when the object is constructed with lets say a constructor without arguments, this object is able/"allowed" to use a certain subset of the methods defined in the class, and when the object is created with a different constructor (for example with arguments) it is able/"allowed" to use a different subset of the methods defined in the class.
These are the conceptual solutions that spring to mind:
Use reflection in the constructors to modify the visibility/accessibility of its class methods. (Problem with this is EURGH... reflection)
Set boolean flags like isAllowedToUseMethodA in the constructor to identify which methods the object will be allowed to use. (Problem with this is the overhead the boolean checks will impose and also methods which are flagged as inaccessible will still be visible to the object and can be attempted to execute)
The obvious elephant in the room answer to this is "Make 2 different classes." and I understand that, I'm just curious is there an elegant way to do this if I want to do this in a single class?
Both options 1 and 2 have a multitude of problems, however fortunately there is a simple and reasonably elegant way to do exactly what you want:
Use inheritance.
Define different versions of the object all inheriting off a common (potentially abstract) core.
Then have factory methods that construct the correct version of each one depending on which factory method you call.
You can't actually use a different subset of methods, but you can kind of 'switch' by means of the strategy pattern.
E.g. for your constructors you set different strategies:
public class XXX() {
method1Strategy = new method1Strategy1();
method2Strategy = new method2Strategy1();
}
public class XXX( ... ) {
method1Strategy = new method1Strategy2();
method2Strategy = new method2Strategy2();
}
And in your methods you execute the concrete strategy:
public Object method1(...) {
return method1Strategy.execute(...)
}
public Object method2(...) {
return method2Strategy.execute(...)
}

Categories

Resources