【问题标题】:Java Listener interface to Scala [closed]Scala的Java侦听器接口[关闭]
【发布时间】:2013-03-05 17:16:35
【问题描述】:

我有这种带有监听器的 Java 源代码。

public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(int position);
    }
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(
                "Activity must implement OnArticleSelectedListener");
        }
    }
    ...
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Send the event to the host activity
        mListener.onArticleSelected(position);
    }
}

而我是这样实现的:

public class MyActivity implements FragmentA.OnArticleSelectedListener {
    ...
    @Override
    public void onArticleSelected(int pos) {
        // do something
    }
}

所以,现在我想将它转换为 Scala。我想,我应该使用特质。 [已解决:在这堂课中,我在onAttach 中遇到了not found: value OnArticleSelectedListener 的错误]:

class FragmentA extends ListFragment {
    var mListener: OnArticleSelectedListener = null
    ...
    trait OnArticleSelectedListener {
        def onArticleSelected(position: Int)
    }
    ...
    override def onAttach(activity: Activity) {
        super.onAttach(activity)
        mListener = (OnArticleSelectedListener) activity;
    }
    ...
    override def onListItemClick(l: ListView, v: View, position: Int, id: Long) {
        // Send the event to the host activity
        mListener.onArticleSelected(position);
    }
}

在 Activity 中,我不知道如何“实现” trait。我知道关键字是“with”,但extends ... with FragmentA.OnArticleSelectedListenerextends ... with OnArticleSelectedListener 显示错误not found: type FragmentAnot found: type OnArticleSelectedListener

有人知道如何解决这个问题吗?

【问题讨论】:

    标签: java scala interface


    【解决方案1】:

    在 Scala 中,您可以使用 asInstanceOf[Foo] 进行转换。在这种情况下,Scala 编译器认为您指的是一个名为 OnArticleSelectedListener 的值,但找不到它,因为它不是值而是类型。要将activity 转换为OnArticleSelectedListener,您可以使用以下代码:

    activity.asInstanceOf[OnArticleSelectedListener]
    

    但是,首选方法是使用here 所述的模式匹配。如果你采用这种方法,你可以这样写:

    mListener = activity match {
        case myActivity: OnArticleSelectedListener => activity
        case _ => throw new ClassCastException 
    }
    

    在这种情况下,我会坚持使用asInstanceOf,因为语义完全相同,而且更简洁。

    如果您将OnArticleSelectedListener 的定义移到FragmentA 类之外,您应该可以像这样扩展它:

     trait OnArticleSelectedListener { def onArticleSelected(position: Int) }
     class MyActivity extends OnArticleSelectedListener {
       def onArticleSelected(position: Int) { ... }
     }
    

    【讨论】:

    • 我必须写:case myActivity: OnArticleSelectedListener => myActivity 否则我会收到错误:type mismatch; found : android.app.Activity required: FragmentA.this.OnArticleSelectedListener
    • 这听起来你可能输入了错误的Activity
    • 是的,我认为,首先我必须完成MyActivity,但我不知道如何正确“实施”和处理这个特征。在 Java 中,我可以编写 implements FragmentA.OnArticleSelectedListener 并覆盖该方法。在 Scala 中?
    • 效果很好!谢谢!