【问题标题】:Android - "No enclosing instance of type 'some.abstract.class.name' class is in scope" error when extendedAndroid - 扩展时出现“范围内没有‘some.abstract.class.name’类的封闭实例”错误
【发布时间】:2016-11-09 05:00:36
【问题描述】:

我有一个来自外部库的抽象适配器类:

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
        }
    }
}

我的适配器扩展了那个适配器

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);
    }
}

如果我的ViewHolderForChecklistChecklistAdapter 的内部类,它可以正常工作。但是如果我将ViewHolderForChecklist 移动到一个全新的类

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;
    }
}

实时有错误

范围内没有“library.package.name.DragItemAdapter”类的封闭实例

以及编译时的错误

错误:需要包含 DragItemAdapter.ViewHolder 的封闭实例

使用 Refractor 中的“移动”有同样的问题。我对这种......“嵌套类”仍然很陌生,所以我不知道这有什么问题,或者我应该包含更多什么样的信息。

谢谢!

【问题讨论】:

标签: java android abstract-class extends android-viewholder


【解决方案1】:

ViewHolderDragItemAdapter内部类(因为它没有被声明为static)。这意味着ViewHolder 类的每个对象都必须与DragItemAdapter 类的对象相关联(实际上,它必须是DragItemAdapter 的子类)。你可以认为ViewHolder 有一个隐藏的实例变量,比如

DragItemAdapter __outerObject;

ViewHolder可以直接访问属于__outerObject的实例变量和方法。

这意味着当您说new ViewHolder(...) 时,您必须有一些DragItemAdapter 才能与ViewHolder 关联。

这同样适用于ViewHolder 的任何子类,包括ViewHolderChecklist,因为子类继承了隐藏的__outerObject 变量。

在第一个示例中,ViewHolderChecklistChecklistAdapter 中,onCreateViewHolder 方法将始终在 ChecklistAdapter 实例上调用。当该方法显示new ViewHolderChecklist 时,新对象的__outerObject 将设置为ChecklistAdapter 实例。此外,如果一个外部类有一个ChecklistAdapter adapter;,它可以通过说adapter.new ViewHolderChecklist(...) 来使用它来创建一个新的ViewHolderChecklist

但是,当您将ViewHolderChecklist 移到类之外时,无法创建新实例,因为无法以一种可以告诉它__outerObject 应该做什么的方式使用new是。 adapter.new ViewHolderChecklist(...) 语法不起作用,因为该语法只允许用于嵌套类,而 ViewHolderChecklist 不是嵌套类。所以ViewHolderChecklist 必须是DragItemAdapter 的子类中的嵌套类。

更正:实际上可以像这样声明ViewHolderChecklist。但是,您必须给它一个显式构造函数,并且它必须有一个合格的超类构造函数调用(参见this;另请参见https://stackoverflow.com/questions/40501642/what-rule-prohibits-this-nested-class-reference/40501815

【讨论】:

  • 感谢您的详细解释。您的“必须是嵌套类”的结论证明这是不可能的,并且可以节省大量寻找解决方案的时间。
  • 请参阅我的更正,尽管它很可能涉及您不想使用的构造。
  • 谢谢,我去看看。
  • 哇,只需编辑几行就可以了。将ChecklistAdapter 的实例传递给视图持有者return new ViewHolderForChecklist(view,grab,this);,然后使用该实例在ViewHolderForChecklist 类中调用超级adapter.super(itemView, grab);。但是你能告诉我你为什么说“你不想使用”吗?我觉得有点简单
  • 好吧,那么,不想使用它。在我看来,它可以使代码更加晦涩难懂。另一方面,如果有充分的理由这样做,这些理由可能会超过我的反对意见。也许有一天我会遇到一个我想要使用它的案例。
猜你喜欢
  • 1970-01-01
  • 2014-04-02
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
相关资源
最近更新 更多