我在设计一个通信类时遇到了一个泛型问题.
首先,有两种类型的操作:查询和变异.每一种的定义如下.
interface Operation<D : Operation.Data> : Executable<D> {
interface Data : Executable.Data
}
interface Query<D : Query.Data> : Operation<D> {
interface Data: Operation.Data
}
interface Mutation<D : Mutation.Data> : Operation<D> {
interface Data: Operation.Data
}
这些接口在library中,不能更改.
我可以 for each 查询和Mutations 创建以下Caller类.
class QueryCaller<T: Query<Data>, Data: Query.Data, Model>(
val operation: T,
val toModel: (Data) -> Model
) {
suspend fun call(client: ApolloClient): Model? {
val data = client.query(operation).execute().data ?: return null
return toModel(data)
}
}
class MutationCaller<T: Mutation<Data>, Data: Mutation.Data, Model>(
val operation: T,
val toModel: (Data) -> Model
) {
suspend fun call(client: ApolloClient): Model? {
val data = client.mutation(operation).execute().data ?: return null
return toModel(data)
}
}
有没有办法将这两个调用方集成到一个可以处理查询和Mutations 的Caller类中?
我想在下面这样做.但Operation<Data>
不能强制转换为Query<Data>
或Mutation<Data>
,因为Data
的边界不同于Query.Data或Mutation.Data.
class OperationCaller<T: Operation<Data>, Data: Operation.Data, Model>(
val operation: T,
val toModel: (Data) -> Model
) {
suspend fun call(client: ApolloClient): Model? {
val query = operation as? Query<Data>
val mutation = operation as? Mutation<Data>
val data = if (query != null) {
client.query(query).execute().data
} else if (mutation != null) {
client.mutation(mutation).execute().data
} ?: return null
return toModel(data)
}
}
仅供参考,在SWIFT中,我们可以使用where
子句将查询和Mutations 的调用方法分开,如下所示.
struct OperationCaller<T: Operation<Data>, Data: Operation.Data, Model> {
let operation: T
let toModel: (Data) -> Model
func call(client: ApolloClient): Model? where T: Query {
guard let data = client.query(operation).execute().data else { return nil }
return toModel(data)
}
func call(client: ApolloClient): Model? where T: Mutation {
guard let data = client.mutation(operation).execute().data else { return nil }
return toModel(data)
}
}
最后,这些示例代码是一个简化版本;实际上,它稍微复杂一些.