Implement interface with suspend function from kotlin in java class - kotlin

I have kotlin Interface with name MediaBucketProvider. this interface
have 1 suspend functuion that return entity list
interface MediaBucketProvider {
suspend fun getMediaBuckets(bucketType: BucketType): List<MediaBucket>
}
When implementing this interface into kotlin class it worked fine. but when i want to
implement this interface in java class like this
class BucketProviderImpl implements MediaBucketProvider {
#Nullable
#Override
public Object getMediaBuckets(#NotNull BucketType bucketType, #NotNull Continuation<? super List<? extends MediaBucket>> $completion) {
//return buckets
}
}
build failed with below error
BucketProviderImpl.java:14: error: BucketProviderImpl is not abstract and does not override abstract method getMediaBuckets(BucketType,Continuation<? super List<MediaBucket>>) in MediaBucketProvider
class CustomLoaderJavaClass implements MediaBucketProvider {
^
When i remove suspend modifier from interface function build not failed anymore.
I see the kotlin-to-java implementation of Kotlin class that implement MediaBucketProvider interface its not different between BucketProviderImpl and java code of KotlinBucketProviderImpl

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")
}

Can a abstract class include non-abstract class parameter in Kotlin?

The Code A is from the aritcle https://developer.android.com/training/dependency-injection/hilt-android
In my mind, a abstract class can not include non-abstract class .
But the function abstract fun bindAnalyticsService( analyticsServiceImpl: AnalyticsServiceImpl): AnalyticsService accept a non-abstract class parameter, why?
Code A
interface AnalyticsService {
fun analyticsMethods()
}
// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
class AnalyticsServiceImpl #Inject constructor(
...
) : AnalyticsService { ... }
#Module
#InstallIn(ActivityComponent::class)
abstract class AnalyticsModule {
#Binds
abstract fun bindAnalyticsService(
analyticsServiceImpl: AnalyticsServiceImpl
): AnalyticsService
}

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 ?

Implement optional functions in an abstract class

In Kotlin I have an abstract class that other classes can inherit from. I would like to have some functions that the class that inherits this class can optionally implement. In the code below, the function is protected abstract. This however requires that the class that is inheriting this class MUST implement these functions. Is there a way to make it so that the class that is inheriting can choose to implement the functions or not implement them?
abstract class BaseDialogFragment {
protected abstract fun getButton1Text(): String
protected abstract fun getButton2Text(): String
}
It is very simple, you just provide the default implementation like in the example below and your inheritors can override them:
abstract class BaseDialogFragment {
open fun getButton1Text(): String {
TODO("Your default implementation here")
}
open fun getButton2Text(): String {
TODO("Your default implementation here")
}
}

Class is not abstract and does not implement abstract base class member

I'm confused by this Kotlin error associated with providing an implementation for an abstract class that has been imported from a maven package.
I have a maven library that is written in Kotlin and exposes an abstract class called APIGatewayRequestHandler. In my app that imports the library, I provide an implementation of the abstract class:
class GetWelcomeMessageHandler : APIGatewayRequestHandler<WelcomeMessage>()
fun handleAPIGatewayRequest(input: com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent, context: com.amazonaws.services.lambda.runtime.Context?): WelcomeMessage {
return WelcomeMessage()
}
}
The decompiled abstract class from the library looks like this:
public abstract class APIGatewayRequestHandler<T> public constructor() : com.amazonaws.services.lambda.runtime.RequestHandler<com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent, T> {
public abstract fun handleAPIGatewayRequest(input: com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent, context: com.amazonaws.services.lambda.runtime.Context?): T
public open fun handleRequest(input: com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent?, context: com.amazonaws.services.lambda.runtime.Context?): T {
/* compiled code */
}
}
I get the following error:
Class 'GetWelcomeMessageHandler' is not abstract and does not implement abstract base class member
public abstract fun handleAPIGatewayRequest(input: APIGatewayProxyRequestEvent, context: Context?): WelcomeMessage
I think you're just missing some override keywords. Namely, your abstract class should have it on the handleRequest method:
public abstract class APIGatewayRequestHandler<T> public constructor() : com.amazonaws.services.lambda.runtime.RequestHandler<com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent, T> {
public abstract fun handleAPIGatewayRequest(input: com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent, context: com.amazonaws.services.lambda.runtime.Context?): T
public override fun handleRequest(input: com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent?, context: com.amazonaws.services.lambda.runtime.Context?): T {
/* compiled code */
}
}
And then your GetWelcomeMessageHandler should have it on its handleAPIGatewayRequest method:
class GetWelcomeMessageHandler : APIGatewayRequestHandler<WelcomeMessage>() { // <-- This curly brace was also missing
override fun handleAPIGatewayRequest(input: com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent, context: com.amazonaws.services.lambda.runtime.Context?): WelcomeMessage {
return WelcomeMessage()
}
}