Whats the interface in angle brackets in Kotlin? - kotlin

In Kotlin I often read
class MyFragment : BaseMvpFragment<MvpView, MvpPresenter>(), MvpView {}
whereas MvpView and MvpPresenter are interfaces.. so MyFragment extends BaseMvpFragment<MvpView, MvpPresenter>() but how can I interpret <MvpView, MvpPresenter> ?

The class BaseMvpFragment obviously defines two generic types which are being specified via <MvpView, MvpPresenter>.
Consider the List<T> interface. When you implement it, it looks like this:
class VerySpecialList : List<String> { ... }

They are type parameters; see here.

Related

Kotlinx serialisation, common interface or type class

I am working on a plugin type system where 3rd parties will register classes that will expose data. I don't know exactly what the data will look like but I will enumerate these plugin instances collect the data and I would like to serialise it. A simplified version.
interface DataProvider {
fun getDataThatIsSerializable() : ???
}
What can i set the return type to so that I know that I will be able to serialise it with kotlinx serialisation. I cannot see any common interface that is injected into the class and given thet kotlin doesn't support type classes its not clear how to achieve what I am trying to do?
I considered something like this:
interface DataProvider {
fun getDataThatIsSerializable() : Pair<Any,KSerializer<*>>
}
but i could not pass this into the Json.encodeAsString functions, the types do not match
Are there any other options I can consider?
kotlinx.serialization doesn't like serializing things unless you can tell it exactly what you're working with.
Would it make sense for the DataProvider to be responsible for serializing its own data? Something like:
interface DataProvider {
fun getDataThatIsSerializable() : Any
fun encodeAsJsonString(data: Any) : String
}
#Serializable
data class Foo(val value: Int)
class FooDataProvider : DataProvider {
override fun getDataThatIsSerializable() : Any {
return Foo(7)
}
override fun encodeAsJsonString(data: Any): String {
return Json.encodeToString(Foo.serializer(), data as Foo)
}
}

What is the difference between sealed class vs sealed interface in kotlin

With Kotlin 1.5 was introduce the sealed interface. Even that I know the difference between classes and interfaces, I'm not clear what are the best practices and beneficies of using sealed interface over sealed class
Should I always use interface now even when is a simple case? Or will be a case by case?
Thanks
Obs: Didn't found similar questions, only about sealed classes
A major reason to choose to use a sealed class instead of interface would be if there is common property/function that you don't want to be public. All members of an interface are always public.
The restriction that members must be public can be worked around on an interface using extension functions/properties, but only if it doesn't involve storing state non-publicly.
Otherwise, sealed interfaces are more flexible because they allow a subtype to be a subclass of something else, an enum class, or a subtype of multiple sealed interface/class hierarchies.
I would also add that sealed interface can be chosen instead of a class to mark an object with additional characteristics and use it in the when statement. For example let's say we have some number of classes that inherited from a sealed class Device:
sealed class DeviceItem(val name: String) {
object Camera : DeviceItem("Camera")
object Lamp : DeviceItem("Lamp")
// ... etc, more devices
}
And we need to use an instance of DeviceItem in when statement, but we don't want to handle all the items, only specific items:
fun onDeviceItemClicked(item: DeviceItem) {
when (item) {
// ....
}
}
In this case we should either add all device items to the when statement with an empty body for devices that we don't want to handle, and the code becomes cumbersome, or use else statement to handle those device items with the empty body. But if we use else we will not be notified of the error, when a new device item is added and requires some handling, which can lead to bugs. Starting from Kotlin 1.7 it will be a compilation error if when operator is not exhaustive. So basically to handle such cases we can provide a sealed interface and handle only items, which implement it:
sealed interface ClickableItem
sealed class DeviceItem(val name: String) {
object Camera : DeviceItem("Camera"), ClickableItem
object Lamp : DeviceItem("Lamp")
// ... etc, more devices
}
fun onDeviceItemClicked(item: ClickableItem) {
when (item) {
Camera -> { /* do something */ }
}
}
In this case when a new device item, which implements ClickableItem interface, is added there will be a compilation error, saying that when statement should be exhaustive and we must handle it.

Implement a Kotlin interface in another file

I'd like to implement some interface methods in another file, using extensions.
I have a feeling it's not possible, but I'd love to do that.
Is this possible?
Here is the idea :
MyClass.kt
class MyClass : MyInterface {
}
MyClassExtension.kt
override MyClass.MyInterface.method1() {
}
override MyClass.MyInterface.method2() {
}
That is not possible to implement the interface in the other file. There are still some possibilities.
You may split your implementation into several abstract classes, e.g. abstract class A : Interface, abstract class B : A and so on. Each class can be in its own file.
The second alternative, that does not let one implement an interface, rather split method implementations is called extension functions.
https://kotlinlang.org/docs/reference/extensions.html
Extension functions are only able to access public API of a class. Extension functions cannot implement interface methods in that case.
Use the following syntax for the declaration:
fun MyClass.method2() { ... }

Extending Classes in Kotlin's Generics

I am trying to implement this enum with simple constructor as follows:
enum class WithGraphicKind(val innerClass: Class<*>) {
CONTACT(Contact::class.java), SALE(Sale::class.java);
}
As both Contact and Sale classes implement a common interface WithGraphics, I would like to type the constructor as innerClass: Class<WithGraphics>, however that does not work. I also tried Class<* : WithGraphics> and similar others, but nothing works. I also couldn't find any hint in official documentation here: https://kotlinlang.org/docs/reference/generics.html
You need declaration-site variance Kotlin Generics: Declaration-site variance
If you tell the compiler that you'll only consume WithGraphics, the compiler allows any subtype of WithGraphics
enum class WithGraphicKind(val innerClass: Class<out WithGraphics>) {
CONTACT(Contact::class.java), SALE(Sale::class.java);
}
enum class WithGraphicKind(val innerClass: Class<out WithGraphics>)
which is basically the equivalent to Java's
Class<? extends WithGraphics>

Kotlin Wildcard Capture on List Callback Parameter

Java:
public class JavaClass implements ModelController.Callback {
#Override
public void onModelsLoaded(#NonNull List<? extends Model> models) {
doSomething(models);
}
private void doSomething(List<Model> models) { }
}
Kotlin:
class ModelController {
var callback = WeakReference<Callback>(null)
interface Callback {
fun onModelsLoaded(models: List<Model>)
}
fun someFunction() {
callback.get().onModelsLoaded(ArrayList<Model>())
}
}
interface Model {
}
Without the ? extends Model in the Java onModelsLoaded method, the override doesn’t match the interface made in Kotlin. With it, I get the following error:
doSomething(<java.util.List<com.yada.Model>) cannot be applied to (java.util.List<capture<? extends com.yada.Model>>)
Why is the wildcard capture required and why doesn't it allow it to be used against the non-wildcard method?
The issue stems from Kotlin collections being variant, and Java only having use-site variance which is implemented though wildcards (capture is something connected to wildcards but not exactly the ? extends ... syntax itself).
When in Kotlin we say List<Model> it means "read-only list of Model or subtypes of Model", when we say the same in Java it means "mutable list of exactly Model and nothing else". To mean roughly what Kotlin's List<Model> means, in Java we have to say List<? extends Model>, this is why for the override to work you have to add the wildcard into the Java code.
Now, your doSomething is written in Java and says that it wants "a list of exactly Model", and when you are giving it "a list of Model or its subtypes", the Java compiler complains, because it can be dangerous: doSomething might try to do something that is not legitimate for a list of, say, ModelImpl, because it thinks it's working on a list of Model.
As of now (Kotlin Beat 2), you have two options:
use MutableList<Model> in your Kotlin code - this mean exactly what Java's List<Model> means, or
define doSomething so that it takes List<? extends Model>, which is what your current Kotlin code means.
In the next update of Kotlin we'll add an annotation on types to facilitate a somewhat cleaner workaround for this problem.
To solve the problem with capture<? extends Model>
You may do something like this:
void doSomething(List<Model> models) {
new ArrayList(models)
}