override function with concrete type parameter - kotlin

Hi I would like know why the following example doesn't work
abstract class BaseClass {
}
class ConcretClasOne : BaseCalculator {
}
class ConcretClasTwo : BaseCalculator {
}
abstract class BaseRun {
abstract fun run(param: BaseClass): Int
}
class ConcretRun : BaseRun {
override fun run(param: ConcretClasOne): Int {
return 0
}
}
this shows me a message run overrides nothing.
I suppose that kotlin isn't able to match the abstract class and the concrete implementation, but what other alternative is there to emulate this behavior, that the run method in the concrete class ConcretRun should receive a concrete param ConcretClasOne?

Generics
Using generics, you can make the base class have a type extending the base class, so that the run method can take that type in.
abstract class BaseClass {
}
class ConcretClasOne: BaseCalculator {
}
class ConcretClasTwo: BaseCalculator {
}
abstract class BaseRun<T: BaseClass> {
abstract fun run(param: T): Int
}
class ConcretRun: BaseRun<ConcretClasOne> {
override fun run(param: ConcretClasOne): Int {
return 0
}
}
Why your code doesn't work
At the moment you are trying to override a method with a more specific type, but as the more general base method can accept more types the more specific method cannot override it.

Related

Kotlin concrete class extending from abstract class and interface, with the interface using a method implemented in the abstract class

I want to ask a question that I have some clues about, but I don't want to influence the answers I will get. I have the following class hierarchy:
abstract class MyAbstractClass {
fun displayStuff(id: String) {
println("My id is $id.")
}
}
interface MyInterface {
fun displayThis() {
displayStuff("some-value")
}
fun displayStuff(id: String) // Not implemented here
}
class MyConcreteClass(): MyAbstractClass(), MyInterface {
fun doStuff() {
displayThis()
}
}
fun main() {
val result = MyConcreteClass()
result.doStuff()
result.displayStuff("id")
}
What's wrong with this design, and how do you suggest I fix it?
It would probably not be a bad idea to extract the displayStuff into another interface. Then MyAbstractClass and MyInterface can both derive from the same interface.
One overrides the displayStuff function, hence providing something like an abstract base implementation for the interface.
The other one is using the function in a specific way, thereby extending the functionality of the interface.
interface DisplayStuff {
fun displayStuff(id: String)
}
abstract class MyAbstractClass: DisplayStuff {
override fun displayStuff(id: String) = println("My id is $id.")
}
interface MyInterface : DisplayStuff {
fun displayThis() = displayStuff("some-value")
}

Swift enum nested class VS Kotlin sealed class. Cant understand

I have code in Swift.
enum QuestionnaireViewMode {
case add(input: Add)
case edit(input: Edit)
enum Add {
case building(input: BuildingInput)
case car(input: CarInput)
case park
struct BuildingInput {
let address: String
let placeName: String
}
struct CarInput {
let name: String
}
}
enum Edit {
case profile(input: ProfileInput)
struct ProfileInput {
let name: String
}
}
}
This is enum class which very easy to use, for example i can create different type of object just like this: .add(input: .car(input: .init(name: "bmw"))). But for me not clear enum classes in kotlin, i found some similar - sealed class and i tryed converted to:
sealed class QuestionnaireViewMode {
sealed class add(input: Add)
sealed class edit(input: Edit)
sealed class Add {
sealed class building(input: BuildingInput)
sealed class car(input: CarInput)
sealed class park
data class BuildingInput(val address: String, val placeName: String)
data class CarInput(val name: String)
}
sealed class Edit {
sealed class profile(input: ProfileInput)
data class ProfileInput(val name: String)
}
}
is this correct?
Your sealed classes need to extend their parent. And you are using sealed class instead of fun for your builder functions, which doesn’t make sense. But since these are classes you don’t need that because you can call the constructors directly. Also, since you have no commonly shared state, these can be sealed interfaces instead of sealed classes, which is a little simpler because you don’t have to worry about constructors.
Here is how I would design it:
sealed interface QuestionnaireViewMode {
sealed interface Add: QuestionaireViewMode {
data class BuildingInput(val address: String, val placeName: String): Add
data class CarInput(val name: String): Add
}
sealed interface Edit: QuestionaireViewMode {
data class ProfileInput(val name: String): Edit
}
}
Usage:
val myInput: QuestionaireViewMode =
QuestionaireViewMode.Add.CarInput(“bmw”)

in kotlin, how to access protected static member in parent class from sub class

It is code worked in java but after convert to kotlin it does not compile.
Having a base class which has some defines as static protected member in the companion object:
abstract class ParentClass {
companion object {
#JvmField
final protected val SERVICE_TYPE_A = "the_service_type_a"
}
}
and the child class:
class ChildClass: ParentClass {
public override fun getServiceType(): String {
return SERVICE_TYPE_A. //<== got compile error
}
}
it does not compile.
how to access a parent class static protected member from subclass?
You need to use #JvmStatic instead as follows:
abstract class ParentClass {
companion object {
#JvmStatic
protected val SERVICE_TYPE_A = "the_service_type_a"
}
abstract fun getServiceType(): String
}
The final keyword in SERVICE_TYPE_A is redundant since everything is final by default in Kotlin. This also mean that if you want ParentClass to be extended, then you need to explicitly define it as open.
Then your ChildClass would look as follows:
class ChildClass: ParentClass() {
override fun getServiceType(): String {
return SERVICE_TYPE_A
}
}

Dagger #Provides in Kotlin

I'm trying to understand Dagger. I created applicationInjector class :
class BaseApplication : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication>? {
return DaggerAppComponent.builder().application(this)?.build()
}
}
And here's my AppComponent
#Component(
modules = [AndroidSupportInjectionModule::class,
ActivityBuilderModules::class]
)
interface AppComponent : AndroidInjector<BaseApplication> {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application?): Builder?
fun build(): AppComponent?
}
}
Now what I want to do is to to inject simple String to Activity (really basic, right ?)
In Java it works like this :
#Module
abstract class ActivityBuilderModules {
#ContributesAndroidInjector
abstract fun contributeAuthActivity() : AuthActivity
//JAVA
#Provides
public static String provideTestString() {
return "TEST "
}
however we don't have static function in Kotlin, right ? And it needs to be static cause I'm getting an error :
error: com.example.kotlintests.di.ActivityBuilderModules is abstract and has instance #Provides methods. Consider making the methods static or including a non-abstract subclass of the module instead.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.example.kotlintests.BaseApplication> {
I tried with package level function but it didn't work. How can I add provideTestString function in Kotlin ?

Type mismatch with generic parameter

I'm trying to run the following code, but I'm getting the following compiler error: Error:(12, 9) Type mismatch: inferred type is Child but Parent<Any> was expected.
abstract class Parent<T> {
abstract fun hi()
}
class Child: Parent<String>() {
override fun hi() {
println("Hi from child")
}
}
fun main(args: Array<String>) {
println("Hello, world!")
test(Child())
}
fun test(parent: Parent<Any>) {
parent.hi()
}
But the Java's equivalent, works as expected:
public class HelloWorld {
public static void main(String[] args) {
test(new Child());
}
public static void test(Parent object) {
object.hi();
}
}
abstract class Parent<T> {
public abstract void hi();
}
class Child extends Parent<String> {
public void hi() {
System.out.println("Hi from child");
}
}
What is wrong with the Kotlin code?
You want Parent<String> to be a subtype of Parent<Any>. Since String is a subtype of Any, what you're looking for is called covariance. You can mark the type parameter of Parent to behave this way with the out keyword:
abstract class Parent<out T> {
abstract fun hi()
}
See more about variance in the official documentation.
As for why the Java example works, #Carcigenicate already mentioned in the comment above that you're using raw types there, e.g. the parent parameter of your test function doesn't have a type parameter at all. You can achieve something similar with a star projection in Kotlin, if you really have to:
fun test(parent: Parent<*>) {
parent.hi()
}