1

I have this kind of Java source code with a Listener.

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

And I implement it in this way:

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

So, now I want to transform it to Scala. I think, I should use traits. [SOLVED: In this class I get the error in onAttach that 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);
    }
}

In the Activity, I do not know how to "implement" the trait. I know the keyword is "with", but extends ... with FragmentA.OnArticleSelectedListener and extends ... with OnArticleSelectedListener displays the error not found: type FragmentAor not found: type OnArticleSelectedListener.

Anyone an idea how to solve this problem?

Tim
  • 13,228
  • 36
  • 108
  • 159

1 Answers1

2

In Scala, you can cast using asInstanceOf[Foo]. In this case, the Scala compiler thinks you are referring to a value called OnArticleSelectedListener but cannot find it, because it's not a value but a type. To cast activity to an OnArticleSelectedListener, you could use this code:

activity.asInstanceOf[OnArticleSelectedListener]

However, the preferred approach is to use pattern matching as described here. If you take this approach, you could write:

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

I would stick with the asInstanceOf in this case, because the semantics are exactly the same and it's more concise.

If you move the definition of OnArticleSelectedListener outside of the FragmentA class, you should be able to extend it like this:

 trait OnArticleSelectedListener { def onArticleSelected(position: Int) }
 class MyActivity extends OnArticleSelectedListener {
   def onArticleSelected(position: Int) { ... }
 }
Community
  • 1
  • 1
yakshaver
  • 2,472
  • 1
  • 18
  • 21
  • I had to write: ``case myActivity: OnArticleSelectedListener => myActivity`` otherwise I get the error: ``type mismatch; found : android.app.Activity required: FragmentA.this.OnArticleSelectedListener`` – Tim Mar 05 '13 at 17:47
  • This sounds like you might have imported the wrong `Activity`. – yakshaver Mar 05 '13 at 17:54
  • Yes, I think, first I had to finish the ``MyActivity``, but I do not know how to "implement" and handle this trait correctly. In Java I can write ``implements FragmentA.OnArticleSelectedListener`` and override the method. In Scala? – Tim Mar 05 '13 at 18:21