Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:是否要求函数参数是某个类的成员?_Scala_Methods - Fatal编程技术网

Scala:是否要求函数参数是某个类的成员?

Scala:是否要求函数参数是某个类的成员?,scala,methods,Scala,Methods,我想做一些像 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) 但现在我可以传入一个具有此签名的任意函数,这可能是不需要的。无论如何,有没有办法确保我传入的

我想做一些像

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)

但现在我可以传入一个具有此签名的任意函数,这可能是不需要的。无论如何,有没有办法确保我传入的函数是某个类的成员?

好吧,如果你不介意一些曲解,你可以利用函数毕竟是一个类的事实

// 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
但是foo将不接受
Int=>String
签名

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)
                  ^
scala>valitos=(i:Int)=>i.toString
itos:Int=>String=
scala>foo(itos)
:11:错误:类型不匹配;
找到:Int=>String
必需:MyIntToString
foo(itos)
^

也许您可以传递一个,然后将其称为
theAInstance.f
?您可以尝试使用反射。@om nom nom我稍微修改了这个问题,以便更好地澄清。请注意,我有多个
A
成员方法满足此签名(包括
f1
f2
),关键是让用户选择使用哪一个。@Ptharien的回答是的,这肯定是一个解决方案,我相信这是我们编写java或其他东西时唯一的解决方案。但是因为在scala中我们可以做
foo(a:{def f1:Unit})
(这是通过java中的反射实现的,如果不允许修改现有类的话!),我只是想知道“反向”是否也是可能的。@Kane我不这么认为,因为与Objective-C不同,scala没有
SEL
类型。为了防止用户创建“错误的”
MyIntToString
的实例,它可能有一个私有的主构造函数。您肯定不想在每次调用时重新关联函数,所以将f1和f2转换为VAL是个好主意。@AlexeyRomanov如果我误解了您的意思,很抱歉,但我不是在实例化
MyIntToString
我是在子类化它(好吧,我是在子类化它并实例化它的匿名子类)。MyIntToString可以制作成
密封的
,并保存在与
A
相同的文件中,如果其目的是将其使用限制在类中A@PaoloFalabella嗯,匿名子类的实例也是
MyIntToString
的实例。是的,把它密封起来也行。@AlexeyRomanov你说得对,对不起。我忘了你不能只使用私有构造函数对类进行子类化。