4

Android 用の scala Views ヘルパーを作成したい

この特性とクラスの組み合わせを使用する

class ScalaView(view: View) {
  def onClick(action: View => Any) =
    view.setOnClickListener(new OnClickListener {
      def onClick(view: View) {
        action(view)
      }
    })
}

trait ScalaViewTrait {
  implicit def view2ScalaView(view: View) =
    new ScalaView(view)
}

そのように onClick() を書くことができます

class MainActivity extends Activity with ScalaViewTrait {
//....
val textView = new TextView(this)
textView.onClick(v => v.asInstanceOf[TextView] setText ("asdas"))
}

私の懸念は、キャストvを避けたいということですTextView

vTextView適用される場合は常にTextView LinearLayout適用さLinearLayoutれます。

v適用されるビューに動的にキャストされる方法はありますか?

Scala を始めたばかりで、これについてあなたの助けが必要です。

アップデート

解決済み 以下の私の回答を参照してください

4

3 に答える 3

3

ここでの問題は、Android API を考えると、完全な型安全性、関連するView.

あなたのアプローチは型の安全性を犠牲にし、ドレキシンの犠牲は(いくつかの)利便性です。あなたと同じように、Android ライブラリに適切な動作を期待するのは合理的であるため、この状況ではタイプ セーフを放棄しても構わないと思っていますが、不快感を少し違った方法でカプセル化します。

OnClickListenerまず、次のようなラッパーを定義します。

case class MyOnClickListener[V <: View](action: V => Any)
  extends OnClickListener {
  def onClick(view: View) = try action(view.asInstanceOf[V]) catch {
    case e: ClassCastException =>
      throw new RuntimeException("This should never happen!", e)
  }
}

そして、それがOnClickListener存在することを忘れてください(または、少なくとも私のコードの他の場所では絶対に使用しないでください)。これで、タイプ セーフでないものはすべて 1 か所にまとめられ、ScalaViewクラスはクリーンになりました。次に例を示します。

class ScalaView[T <: View](view: T) {
  def onClick(action: T => Any) =
    view.setOnClickListener(MyOnClickListener(action))
}

この種のラッパーが必要な他の場所に出くわす可能性があります。このアプローチにより、コード全体に散らばるのではなく、すべての醜いキャストなどを 1 つの場所に慎重に含めることができます。

于 2012-09-02T18:32:45.303 に答える
2

なんとかできました。方法は次のとおりです

trait ScalaViewTrait {
  implicit def view2ScalaView[T <: View](view: T) =
    new ScalaView[T](view)
}

class ScalaView[T <: View](view: T) {
  def onClick(action: T => Any) =
    view.setOnClickListener(new OnClickListener {
      def onClick(view: View) {
        action(view.asInstanceOf[T])
      }
    })
}

そして今、私はこのように onClick を書くことができます

textView.onClick(v => v.setText("asdsa"))

vが実際に適用されるTextViewときonClickTextView

PS。たぶん、たくさんのヘルパーを書いて GitHub に公開するつもりです。<3 スカラ

于 2012-09-02T15:59:36.790 に答える
1

キャストする代わりに、単純にパターンマッチすることができます:

// ...
textView.onClick {
  case v: TextView => v.setText("foobar")
  case v => log.error("Expected TextView got %s.".format(v.getClass))
}
于 2012-09-02T15:34:31.303 に答える