Radoslav Yordanov
Radoslav Yordanov

Reputation: 735

Assign any type to a variable

I have two objects from different types:

ObservableListView listView;
ObservableGridView gridView;

Is it possible to make a variable that will assign one of the objects based on some condition. And after that to call their methods? Is it something with Generic Types? Sorry if it has been asked, I don't know how is called this technique.

Edit: I'm trying to avoid code duplication:

if (phone) {
        listView = (ObservableListView) getActivity().findViewById(R.id.castdetailscredits);
        if (listView != null) {
            listView.setOnItemClickListener(this);
            listView.setScrollViewCallbacks(activity.getCastDetailsFragment());
            listView.setTouchInterceptionViewGroup((ViewGroup) activity.getCastDetailsFragment().getView().findViewById(R.id.containerLayout));
            Bundle save = activity.getCastDetailsCreditsBundle();
            if (save != null) {
                moviesList = save.getParcelableArrayList("moviesList");
                movieAdapter = new MovieAdapter(getActivity(), R.layout.row, this.moviesList);
                listView.setAdapter(movieAdapter);
            }

        }
    } else {
        gridView = (ObservableGridView) getActivity().findViewById(R.id.castdetailscredits);
        if (gridView != null) {
            gridView.setOnItemClickListener(this);
            gridView.setScrollViewCallbacks(activity.getCastDetailsFragment());
            gridView.setTouchInterceptionViewGroup((ViewGroup) activity.getCastDetailsFragment().getView().findViewById(R.id.containerLayout));
            Bundle save = activity.getCastDetailsCreditsBundle();
            if (save != null) {
                moviesList = save.getParcelableArrayList("moviesList");
                movieAdapter = new MovieAdapter(getActivity(), R.layout.row, this.moviesList);
                gridView.setAdapter(movieAdapter);
            }

        }
    }

Upvotes: 1

Views: 115

Answers (1)

d0nut
d0nut

Reputation: 2834

There's a couple of ways to do this actually:

Reflection:

//I don't know this object so I'm using a default constructor
ObservableListView listView = new ObservableListView(); 
ObservableGridView gridView = new ObservableGridView();

Object obj;

if(condition)
{
    obj = listView;
}
else
{
    obj = gridView;
}

Method method = obj.getClass().getMethod("methodname", param1.getClass(), param2.getClass());
try
{
    method.invoke(obj, param1, param2);
}catch(Exception e){}

Inheritance:

//assuming that there is some parent class of both classes that contains methods that you would like to use
ObservableListView listView = new ObservableListView(); 
ObservableGridView gridView = new ObservableGridView();

ObservableView view;

if(condition)
{
    view = listView;
}
else
{
    view = gridView;
}

view.someMethod();

Interface:

//this assumes that both ObservableListView and ObservableGridView implement some interface 'IObservableView'
ObservableListView listView = new ObservableListView(); 
ObservableGridView gridView = new ObservableGridView();

IObservableView view;

if(condition)
{
    view = listView;
}
else
{
    view = gridView;
}

view.someMethod();

Instanceof:

//very flexible version. I think that this is the route I would choose
ObservableListView listView = new ObservableListView(); 
ObservableGridView gridView = new ObservableGridView();

Object obj;

if(condition)
{
    obj = listView;
}
else
{
    obj = gridView;
}

if(obj instanceof ObservableListView)
{
    ((ObservableListView)obj).someMethodOnlyInThisClass();
}
else if(obj instanceof ObservableGridView)
{
    ((ObservableGridView)obj).someOtherMethodOnlyInThisClass();
}

I would avoid using reflection.

Inheritance only works if the method you want to use is in both classes and inherited from a super class.

Interfaces work if the super class doesn't have the same method but both child classes do implement the interface.

instanceof is probably the most flexible solution that doesn't use reflection though some look down upon its use.


Since you updated your answer with a more clear objective. Here's what I would do.

AdapterView view = (AdapterView) getActivity().findViewById(R.id.castdetailscredits);

if(view != null)
{
    view.setOnItemClickListener(this);
    ((Scrollable)view).setScrollViewCallbacks(activity.getCastDetailsFragment());
    ((Scrollable)view).setTouchInterceptionViewGroup((ViewGroup) activity.getCastDetailsFragment().getView().findViewById(R.id.containerLayout));
    Bundle save = activity.getCastDetailsCreditsBundle();

    if (save != null) {
        moviesList = save.getParcelableArrayList("moviesList");
        movieAdapter = new MovieAdapter(getActivity(), R.layout.row, this.moviesList);
        view.setAdapter(movieAdapter);
    }
}

We use a couple of techniques here that I mentioned above. Specifically the Inheritance (AdapterView) and Interface (Scrollable).

Upvotes: 1

Related Questions