所以我想说我想创建一个名为ImportFunc的自定义函数类型,它接受一个名为fileImportID的Int和一个名为filename的字符串。我可以使用像这样的类型别名轻松地做到这一点:
type ImportFunc = (Int, String) => Unit
问题是,任何试图使用此函数的人都不知道Int和String实际应该是什么。有什么方法可以写出像:
type ImportFunc = (fileImportID: Int, filename: String) => Unit
答案 0 :(得分:3)
当你调用一个函数时,你实际上调用了函数的apply方法。 换句话说,鉴于此:
def doImport(fileImportID: Int, filename: String) {
println(s"Importing file #$fileImportID ($filename)")
}
以下代码段:
val f = doImport _
f(123, "file.txt")
...只是语法糖:
val f = doImport _
f.apply(123, "file.txt")
如果在使用命名参数进行调用时编译器将查找参数名称的位置,则必须在apply
方法的定义中。
事实证明,在Function2
中,这些参数名为v1
和v2
。所以我们可以这样做:
scala> f.apply(v1=123, v2="file.txt")
Importing file #123 (file.txt)
现在让我们看看它在使用语法糖时是否仍然有效(换句话说,当删除对apply
的显式调用时):
scala> f(v1=123, v2="file.txt")
Importing file #123 (file.txt)
很好,很有效。
当然,v1
和v2
与fileImportID
和filename
并不完全相同,但我们可以通过一些类型细化来解决这个问题:
type ImportFunc = ((Int, String)=>Unit) {
def apply(fileImportID: Int, filename: String): Unit
}
基本上这只是(Int, String)=>Unit
(或者换句话说是Function2[Int, String, Unit]
),但是使用我们想要的参数名称重新定义apply
。
让我们看看这个在行动:
scala> val f: ImportFunc = doImport _
f: ImportFunc = <function2>
scala> f(fileImportID=123, filename="file.txt")
Importing file #123 (file.txt)
成功!
一个重要的旁注:在输入方面,ImportFunc
与Function2[Int, String, Unit]
相同,或与任何其他类似的改进相同。
这是因为参数名称不是签名的一部分。因此,在我的示例f
中仍然可以传递Function2[Int, String, Unit]
(但从那时起,你再也无法使用你的自定义参数名称来调用它了。)
答案 1 :(得分:2)
在Scala中,函数是根据特征FunctionX
定义的,因此您可以执行以下操作:
trait ImportFunc extends ((Int, String) => Unit) {
def apply(fileImportId: Int, filename: String): Unit
}
// Then custom definition can be implemented as following
val f1: ImportFunc = new ImportFunc {
def apply(fid: Int, fn: String): Unit = ???
}
f1(1, "name") // call it
/** Companion object to ease the use */
object ImportFunc {
/** Function factory: take a plain (Int, String) => Unit
and turn it into documented type */
def apply(f: (Int, String) => Unit): ImportFunc = new ImportFunc {
def apply(fileImportId: Int, filename: String): Unit = f(fileImportId, filename)
}
}
val f2: ImportFunc = ImportFunc((fid: Int, fn: String) => ???)
f2(2, "eman") // call it
答案 2 :(得分:1)
简单&#34;类型&#34;溶液:
type FileImportID = Int
type Filename = String
type ImportFunc = (FileImportID, Filename) => Unit
答案 3 :(得分:-1)
我不太喜欢Int和String,因为它们很容易混淆其他字符串和Ints。做:
case class FileImportID(value: Int) extends AnyVal
case class Filename(value: String) extends AnyVal
//Leading to
type ImportFunc = (FileImportID, Filename) => Unit