0

私は何かをしたい

class A {
  def f1: Unit = ...
  def f2: Unit = ...
}
def foo(f: => Unit) {
  (new A).f // ???
}

ここで、f はクラス A のメンバー関数であると想定されています。標準的な解決策は

def foo(f: A => Unit) {
  f(new A)
}

このように使用します

foo(_.f1)
foo(_.f2)

しかし今では、この署名を持つ任意の関数を渡すことができますが、これは望ましくない可能性があります。私が渡す関数が特定のクラスのメンバーであることを確認する方法はありますか?

4

1 に答える 1

2

まあ、いくつかのゆがみを気にしないのであれば、結局のところ、関数はクラスであるという事実を利用できます...

// abstract class MyIntToString extends (Int => String) // declare here if you want 
                                                       // to use from different classes

// EDIT: f1 and f2 are now val instead of def as per comment below
// by @Régis Jean-Gilles
class A {
    abstract class MyIntToString private[A]() extends (Int => String) 
           // if MyIntToString is declared here
           // with a constructor private to the enclosing class
           // you can ensure it's used only within A (credit goes to @AlexeyRomanov 
           // for his comment below)
    val f1 = new MyIntToString {
        def apply(i: Int) = i.toString + " f1"
    }
    val f2= new MyIntToString {
        def apply(i: Int) = i.toString + " f2"
    }
 }

def foo(f: A#MyIntToString) = f(42) // f: MyIntToString if MyIntToString not nested in A
val a = A

今、あなたはできる:

scala> foo((new A).f1)
res1: String = 42 f1

scala> foo((new A).f2)
res2: String = 42 f2

Int => Stringしかし foo は署名を受け入れません

scala> val itos = (i:Int) => i.toString
itos: Int => String = <function1>

scala> foo(itos)
<console>:11: error: type mismatch;
 found   : Int => String
 required: MyIntToString
              foo(itos)
                  ^
于 2012-12-05T21:12:23.850 に答える