Reputation: 247
I've been struggling with this issue for a couple hours and fond no solution. I'am building an android application using MVP pattern and DataBinding, and I wanted to reduce the boilerplate code of creating fragments with a specific binding, using a specific Presenter.
Therefore I declared the following abstract class:
abstract class AbstractBoundFragment : Fragment(), Screen {
protected abstract var presenter: Presenter<Screen>
protected abstract var binding: ViewDataBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = getBinding(inflater, container)
return binding.root
}
override fun onAttach(context: Context) {
super.onAttach(context)
presenter.attachScreen(this)
}
override fun onDetach() {
presenter.detachScreen()
super.onDetach()
}
protected abstract fun getBinding(inflater: LayoutInflater, container: ViewGroup?): ViewDataBinding
}
When I'm extending this class in a concrete fragment, I get the following type error:
"Var-property type is 'FragmentArtistListBinding', which is not a type of overridden protected abstract var binding: ViewDataBinding defined in xy.z.ui.utils.AbstractBoundFragment."
FragmentArtistListBinding
is the class generated by android data binding, and it clearly extends ViewDataBinding
.
I get the same error for the overridden presenter. ArtistsPresenter extends
the abstract Presenter<Screen>
class correctly.
class ArtistListFragment : AbstractBoundFragment(),
ArtistListScreen {
@Inject
override lateinit var presenter: ArtistsPresenter // type error here
override lateinit var binding: FragmentArtistListBinding // and type error here
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentArtistListBinding {
return FragmentArtistListBinding.inflate(inflater, container, false)
}
override fun showArtist(artistName: String) {
// do stuff
}
}
What am I missing here?
Upvotes: 3
Views: 380
Reputation: 200168
As opposed to a val
, which is covariant, a var
type is invariant. Think about the following case:
abstract class Base {
abstract var x: Any
}
class Derived : Base {
override var x: String
}
fun main() {
val base: Base = Derived()
base.x = 1
}
Base.x
is Any
, so why wouldn't you assign it an Int
value of 1
? Yet clearly this is wrong because you're doing it to an instance of Derived
.
Upvotes: 4