Reputation: 1363
I have an abstract adapter class from an external library:
public abstract class DragItemAdapter<T, VH extends DragItemAdapter.ViewHolder> extends RecyclerView.Adapter<VH> {
//Their other codes
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(final View itemView, int handleResId) {
super(itemView);
//The rest of their codes
}
}
}
And I have my Adapter extended that adapter
public class ChecklistAdapter extends DragItemAdapter<Pair<Integer, SomeClass>, ViewHolderForChecklist> {
@Override
public ViewHolderForChecklist onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
grab = R.id.grab;
return new ViewHolderForChecklist(view,grab);
}
}
If my ViewHolderForChecklist
is an inner class of the ChecklistAdapter
it works fine. But if I move the ViewHolderForChecklist
to a brand new class
public class ViewHolderForChecklist extends DragItemAdapter<Pair<Long, SomeClass>, ViewHolderForChecklist>.ViewHolder { // The error is at this line
public ViewHolderForChecklist(final View itemView, int grab) {
super(itemView, grab);
}
@Override
public void onItemClicked(View view) {
}
@Override
public boolean onItemLongClicked(View view) {
return true;
}
}
There is an error in real time
No enclosing instance of type 'library.package.name.DragItemAdapter' class is in scope
and the error when compile
error: an enclosing instance that contains DragItemAdapter.ViewHolder is required
Using "move" from Refractor has the same problem. I'm still new to this kind of... 'nested-class" so I don't know what is wrong with this or what kind of info should I include more.
Thank you!
Upvotes: 2
Views: 492
Reputation: 31699
ViewHolder
is an inner class of DragItemAdapter
(because it wasn't declared static
). That means that every object of class ViewHolder
must be associated with an object of class DragItemAdapter
(actually, it would have to be a subclass of DragItemAdapter
). You can think of ViewHolder
having a hidden instance variable like
DragItemAdapter __outerObject;
The ViewHolder
can directly access instance variables and methods belonging to the __outerObject
.
That means that when you say new ViewHolder(...)
, you have to have some DragItemAdapter
for the ViewHolder
to be associated with.
The same applies to any subclass of ViewHolder
, including ViewHolderChecklist
, since the subclass inherits the hidden __outerObject
variable.
In the first example, where ViewHolderChecklist
is inside a ChecklistAdapter
, the onCreateViewHolder
method will always be called on a ChecklistAdapter
instance. When that method says new ViewHolderChecklist
, the new object's __outerObject
will be set to the ChecklistAdapter
instance. Also, if an outside class has a ChecklistAdapter adapter;
, it can use that to create a new ViewHolderChecklist
by saying adapter.new ViewHolderChecklist(...)
.
When you move ViewHolderChecklist
outside the class, though, there's no way for a new instance to be created, since there's no way to use new
in a way that would tell it what its __outerObject
is supposed to be. The adapter.new ViewHolderChecklist(...)
syntax won't work, because that syntax is only allowed for nested classes, and ViewHolderChecklist
isn't a nested class. So ViewHolderChecklist
has to be a nested class inside a subclass of DragItemAdapter
.
Correction: It's actually possible to declare ViewHolderChecklist
like this. However, you have to give it an explicit constructor and it has to have a Qualified Superclass Constructor Invocation (see this; see also https://stackoverflow.com/questions/40501642/what-rule-prohibits-this-nested-class-reference/40501815.
Upvotes: 1