Reputation: 17
I'm currently learning to split my messy code into DDD (note, learning) paradigm. The entities (IEntity
, IUser
) is domain layer is made up of interface, which then implemented at the Data layer (BaseEntity
, User
). Access to data is through the repository pattern. But as I defined for IUserRepository
to return IUser
, at the data layer I have to manually cast it User
back to IUser
to match the return signature.
How can I avoid the casting? Thank you.
Domain layer
interface IEntity
{
var id: Long?
var name: String?
}
interface IUser : IEntity
{
}
interface IBaseRepository<T: IUser>
{
fun get(id: Long): Observable<T?>
}
interface IUserRepository : IBaseRepository<IUser>
{
}
Data layer
abstract class BaseEntity() : IEntity
{
@SerializedName("id")
override var id: Long? = null
@SerializedName("full_name")
override var name: String? = null
}
class User() : BaseEntity(), IUser
{
}
interface UserRetrofitApi
{
@GET("user/{uuid}/")
fun get(id: Long): Observable<User?>
}
class UserRepository(private val _api: UserRetrofitApi) : IUserRepository
{
override fun get(id: Long): Observable<IUser?> {
return _api.get(id) as Observable<IUser?> // How to avoid casting here without resorting to generic UserRepository<T: IUser>
}
}
Upvotes: 1
Views: 393
Reputation: 100388
Declare your get
function in the base repository as follows:
fun get(id: Long): Observable<out T?>
and likewise change the get
function in UserRepository
to:
override fun get(id: Long): Observable<out IUser?> {
return _api.get(id)
}
See the docs on variance for more information.
Upvotes: 1
Reputation: 295
If I understand you right you just need to change you return the result of UserRetroFitApi.get
to Observable<IUser?>
.
class UserRetrofitApi
{
fun get(id: Long): Observable<IUser?> {
val user = User()
user.id = 1
user.name = "User 1"
return Observable.just(user)
}
}
Upvotes: 0