Ábel Énekes
Ábel Énekes

Reputation: 247

Overriding abstract property of superclass results in type error

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

Answers (1)

Marko Topolnik
Marko Topolnik

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

Related Questions