Emre Aktürk
Emre Aktürk

Reputation: 3346

Extends from type parameter

I am trying to create a generic base class but getting "Cannot extends from its type parameter error"

Here is my class:

package com.akturk.bella.activity;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.v4.app.FragmentActivity;

abstract class BaseActivity<E extends Activity> extends E {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(getContentView());
}

@Override
public void onContentChanged() {
    super.onContentChanged();
    ButterKnife.inject(this);
}

protected abstract
@LayoutRes
int getContentView();
}

What i want to do is pass a class parameter to extends base class from another class like FragmentActivity or ListActivity or something else that extends Activity.

How can i achive my goal?

EDIT :

I want a usage like

public class TestActivity<FragmentActivity> extends BaseActivity

or

public class TestActivity<ListActivity> extends BaseActivity

By doing this, i would able to use ListActivity or FragmentActivity`s spesific methods like getListView() or getSupportedFragmentManager()

Upvotes: 0

Views: 513

Answers (1)

Kulu Limpa
Kulu Limpa

Reputation: 3541

I don't think you can achieve what you want using subtyping. Firstly, Java did not support generics from the beginning. To stay backwards compatible, generic types get erased at runtime, so in your case, dynamically, every instance of E is replaced by Activity, even if you instantiate BaseActivity<ListActivity>.

However, you could try achieving something similar using composition.

abstract class BaseActivity<E extends Activity> {
  public E activity;
  public BaseActivity(E activity){
    this.activity = activity; 
  } 
// ...
}

Which provides you an indirect access to the methods of the generic activity you pass it. However, this means that you cannot polymorphically put BaseActivity where its generic type is required, because it does not subclass it.

Still, what you can do now is (assuming BaseActivityImpl is a non-abstract variant of BaseActivity):

(new BaseActivityImpl<ListActivity>(theListActivityInstance)).activity.getListView()

Edit: Actually, there is an even more fundamental problem if what you want to achieve would actually work:

class Cat<A> extends A {
  String eat(){ return "Cat is eating"; }
}

class Dog {
  void eat(){ System.out.println("Dog is eating"); }
}

What would happen if you called (new Cat<Dog>()).eat();? Cat isn't overriding eat, because the signatures do not match.

Edit2: Also, if the generic superclass does not provide a default constructor, there would be no way of instantiating it.

Upvotes: 1

Related Questions