Scala 作为参数的函数
我有几个具有相同编码模式的函数:Scala 作为参数的函数,scala,Scala,我有几个具有相同编码模式的函数: def updateFooValidationStatus(fooId: Long, user: String, valid: Boolean): Option[Foo] = { val fooMaybe = fooDao.getFooById(activityId) fooMaybe match { case Some(foo) => { fooDao.update(foo.copy(updatedBy = Some(use
def updateFooValidationStatus(fooId: Long, user: String, valid: Boolean): Option[Foo] = {
val fooMaybe = fooDao.getFooById(activityId)
fooMaybe match {
case Some(foo) => {
fooDao.update(foo.copy(updatedBy = Some(user),
validationStatus = if (valid) Some(DataEntryValidationStatus.Valid) else Some(DataEntryValidationStatus.Invalid))
)
}
case None =>
throw new DomainException(s"Foo with ID: '$fooId' doesn't exist")
}
}
为了减少代码的重复,我编写了一个新的私有函数
private def updateDomainObjectValidationStatus(f1: Long => Option[DomainObject],
parameter1: Long,
f2: DomainObject => Option[DomainObject],
paramter2: String,
valid: Boolean ): Option[DomainObject] ={
val somethingMaybe = f1(parameter1)
somethingMaybe match {
case Some(something) =>
f2(
something.copyMe(updatedBy = Some(paramter2),
validationStatus = if(valid) Some(DataEntryValidationStatus.Valid) else Some(DataEntryValidationStatus.Invalid))
)
case None =>
throw new DomainException(s"Object with ID: '$parameter1' doesn't exist")
}
}
在哪里
但是,通过上述更改,我无法在UpdateFovalidationStatus内部调用updateDomainObjectValidationStatus,因为一个参数上存在错误
type mismatch, expected (DomainObject) => Option[DomainObject], actual (Foo) => Option[Foo]
(Long) => Option[DomainObject]
有趣的是,它并没有抱怨第一个参数
type mismatch, expected (DomainObject) => Option[DomainObject], actual (Foo) => Option[Foo]
(Long) => Option[DomainObject]
这需要
(Long) => Option[Foo]
按照Scala的惯用方式,什么样的代码设计才能使上述代码正常工作?这里发生的是:
updateDomainObjectValidationStatus
不能接受类型为(Foo)=>Option[Foo]
的值作为类型为(DomainObject)=>Option[DomainObject]
的参数,因为函数的参数类型是逆变的,返回类型是协变的。这是什么意思
- 如果
扩展A
,那么返回B
的函数将扩展返回A
的函数(这就是为什么编译器不会抱怨您的第一个参数)B
- 但是,如果
扩展A
,则带有B
类型参数的函数将扩展带有B
类型参数的函数,意思是相反的李>A
a
上工作,但不一定在任何B
上工作,对吗?如果函数具有Int
参数,则不能使用AnyVal
类型传递值。。。与此相反的是,可以使用Int
调用AnyVal
上的函数
要解决此问题-在本例中,最好的方法似乎是为updateDomainObjectValidationStatus
提供一个扩展DomainObject
的类型:
private def updateDomainObjectValidationStatus[T <: DomainObject](
f1: Long => Option[T],
parameter1: Long,
f2: T => Option[T],
paramter2: String,
valid: Boolean): Option[T] = { ... }
private def updateDomainObjectValidationStatus[T选项[T],
参数1:长,
f2:T=>选项[T],
参数2:字符串,
有效:布尔):选项[T]={…}
当您使用类型为
(Long)=>Option[Foo]
的第一个参数调用它时,类型T
被推断为Foo
,然后编译器期望第三个参数使用(Foo)=>Option[Foo]
,正如预期的那样。您甚至可以得到一个不错的奖励-返回类型将更加具体:Option[Foo]
而不是选项[DomainObject]
这里发生的是:更新的MainObjectValidationStatus
不能接受类型为(Foo)=>选项[Foo]
的值作为类型为(DomainObject)=>选项[DomainObject]
的参数,因为函数的参数类型是相反的它们的回报类型是协变的。这是什么意思
- 如果
扩展A
,那么返回B
的函数将扩展返回A
的函数(这就是为什么编译器不会抱怨您的第一个参数)B
- 但是,如果
扩展A
,则带有B
类型参数的函数将扩展带有B
类型参数的函数,意思是相反的A
A扩展了B
,我们可以说“A是B”。现在,“A上的函数”可以在任何A
上工作,但不一定在任何B
上工作,对吗?如果您的函数有Int
参数,则不能使用AnyVal
类型传递值……相反的情况确实有效-可以使用Int
调用AnyVal
上的函数
要解决此问题-在本例中,最好的方法似乎是为updateDomainObjectValidationStatus
提供一个扩展DomainObject
的类型:
private def updateDomainObjectValidationStatus[T <: DomainObject](
f1: Long => Option[T],
parameter1: Long,
f2: T => Option[T],
paramter2: String,
valid: Boolean): Option[T] = { ... }
private def updateDomainObjectValidationStatus[T选项[T],
参数1:长,
f2:T=>选项[T],
参数2:字符串,
有效:布尔):选项[T]={…}
当您使用类型为
(Long)=>Option[Foo]
的第一个参数调用它时,类型T
被推断为Foo
,然后编译器期望第三个参数使用(Foo)=>Option[Foo]
,正如预期的那样。您甚至可以得到一个不错的奖励-返回类型将更加具体:Option[Foo]
而不是选项[DomainObject]
def
s不是函数,它们是方法def
s不是函数,它们是方法非常感谢详细的解释。对于更改,我需要参数化DomainObject特性及其子案例类。特性中定义了一个方法签名。我需要在几分钟后解决它修复。非常感谢您的详细解释。对于更改,我需要参数化DomainObject trait及其子案例类。trait中定义了一个方法签名。我需要在多次修复后计算出它。