繁体   English   中英

无法用类型参数将 Java class 重写为 Kotlin

[英]Cannot rewrite Java class with type parameters to Kotlin

我以为我对 Kotlin 的inout*修饰符有很好的了解,但我无法将 class 从 Java 重写为 Kotlin。 也许有人可以帮助我。 在我的应用程序中,我使用的是 retrofit,在我的所有项目中,我都有这个 ApiResponseValidatorJava class,它负责验证 API 响应模型,例如 Customer。 用 Kotlin 编写的 class 看起来如何?

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.HashMap;

import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

public class ApiResponseValidatorJava extends Converter.Factory {

    private HashMap<Type, ModelValidator> validators = new HashMap();

    public ApiResponseValidatorJava(ModelValidator... validators) {
        for (ModelValidator v : validators) {
            this.validators.put(v.getModelType(), v);
        }
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(final Type type, Annotation[] annotations, Retrofit retrofit) {
        final Converter<ResponseBody, Object> mainConverter = retrofit.nextResponseBodyConverter(this, type, annotations);
        return new Converter<ResponseBody, Object>() {
            @Override
            public Object convert(ResponseBody value) throws IOException {
                Object apiResponseModel = mainConverter.convert(value);
                if (validators.containsKey(type)) {
                    validators.get(type).validate(apiResponseModel);
                }
                return apiResponseModel;
            }
        };
    }
}

import java.lang.reflect.Type

interface ModelValidator<T> {
    fun getModelType(): Type
    fun validate(data: T)
}
import retrofit2.Call
import retrofit2.http.*

interface Api {
    @GET("api/session/customer")
    fun getCustomer(): Call<Customer>
}
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class Customer(
    @Json(name = "id")
    val id: String,
    @Json(name = "phone")
    val phone: String
)
class CustomerResponseValidator : ModelValidator<Customer> {
    override fun getModelType() = Customer::class.java

    override fun validate(customer: Customer) {
        if (!customer.phone.startsWith("+212")) {
            throw IllegalAccessException("Phone doesn't start with +212")
        }
    }
}

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    private fun buildRetrofit(): Api {
        val apiResponseValidator = ApiResponseValidatorJava(
            CustomerResponseValidator()
        )

        return Retrofit.Builder()
            .baseUrl("https://example.com/")
            .client(OkHttpClient.Builder().build())
            .addConverterFactory(apiResponseValidator)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
            .create(Api::class.java)
    }

}
// gradle dependecies
implementation group: 'com.squareup.retrofit2', name: 'retrofit', version: '2.6.2'
implementation group: 'com.squareup.retrofit2', name: 'converter-moshi', version: '2.6.2'
implementation group: 'com.squareup.moshi', name: 'moshi', version: '1.8.0'
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.8.0"

由于您希望接收每个泛型类型的ModelValidator作为输入,因此可以使用ModelValidator<out Any?>

你可以使用这样的东西:

class ApiResponseValidatorJava(vararg validators: ModelValidator<out Any?>) : Converter.Factory() {

    private val validators = mutableMapOf<Type, ModelValidator<Any?>>().apply {
        validators.forEach {
            @Suppress("UNCHECKED_CAST")
            this[it.getModelType()] = it as ModelValidator<Any?>
        }
    }

    override fun responseBodyConverter(
        type: Type,
        annotations: Array<Annotation>,
        retrofit: Retrofit
    ): Converter<ResponseBody, *> {
        val mainConverter = retrofit.nextResponseBodyConverter<Any?>(this, type, annotations)
        return Converter<ResponseBody, Any?> { value ->
            mainConverter.convert(value).also { apiResponseModel ->
                validators[type]?.validate(apiResponseModel)
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM