Implementation CrimeListFragment.Callbacks

Hello everyone! First, I wanna say: “Thanks!” - to authors. I like to study android programming with this book.
I have one question about implementation callbacks. I’ve studied in detail:

  • explicit and implicit casts
  • type conversion
  • everything about Interfaces and Interface variables

But, I coudn’t understand one code line: mCallbacks = (Callbacks) context; from

@Override
public void onAttach(Context context) {
super.onAttach(context);
mCallbacks = (Callbacks) context;
}

What exactly is happening here ?! For me this code, as if, to imply that we defined a reference variable whose type is an interface, but at the same time, any object we assign to it must be an instance of a class that implements the interface. About it said on oficial site: Using an Interface as a Type

It follows that context - is an instance of a class Context, which somewhere implemented this interface. So, I understand, that somewhere must exist somethink like this:

class Context implements CrimeListFragment.Callbacks{…}.

And proceeding from this - the following should work:

((Callbacks)getContext()).onCrimeSelected(crime);

And it works!
And also, the following should work:

mCallbacks = context; // without (Callback)

but in this way it does not work.

I hope someone would understand what I do not understand =)

I don’t do Android, but I fully understand your question.

@Override
public void onAttach (Context context) {
    super.onAttach(context);
    mCallbacks = (Callbacks) context;
}

You have already figured out that the last statement in the above code tells the compiler: “Please trust me, the programmer, the type of context is Callbacks.”

If I were you I would find out what the visible type of Context is in the compilation unit containing the above code. You will discover that it is probably an opaque type or a related super type.

public class CrimePagerActivity extends AppCompatActivity
        implements CrimeFragment.Callbacks {
        //......
}
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        mCallbacks = (Callbacks) context;
    }

The context object here is one instance of the class CrimePagerActivity. Since CrimePagerActivity implements CrimeFragment.Callbacks, it’s instance can be cast to the type CrimeFragment.Callbacks.

I did not give up trying to go into the matter, that’s how I see it and if I’m wrong, correct me:

1. In CrimeListFragment we declared the interface and declared the interface variable:

private Callbacks mCallbacks;

public interface Callbacks {
     void onCrimeSelected(Crime crime);
}

2. interface Callbacks (in this case) can exist as a type after its implementation, that is, after:

CrimeListActivity extends SingleFragmentActivity implements CrimeListFragment.Callbacks{…}

3. As

CrimeListActivity … extends AppCompatActivity … extends Activity … extends Context

and we want to use exactly the Context class instance, in the CrimeListFragment class, in the method:

@Override
public void onAttach(Context context) {
super.onAttach(context);
mCallbacks = (Callbacks) context;
}

we assign the value to interface variable by EXPLICIT CASTING (Callbacks). Because, the superclass is assigned to the subclass.

4. At the same time, as I understand it, here is clearly expressed the properties of polymorphism, since the initialization check of interface variable will be executed at run time

Excellent explanation.