用类型 class 扩展案例 class
Extend case class with typeclass
我有这个代码
case class Salary(employee: String, amount: Double){
}
trait XN[M] {
def x2(m: M): M
def x3(m: M): M
def x4(m: M): M
}
我想用 XN 特征扩展 Salary,以便进行以下测试:
test("Salary is extended with xN") {
val bobSalary = Salary("Bob", 100.0)
bobSalary.x2 shouldBe Salary("Bob", 200.0)
bobSalary.x3 shouldBe Salary("Bob", 300.0)
bobSalary.x4 shouldBe Salary("Bob", 400.0)
}
我的尝试:
#1
implicit val SalaryXN: XN[Salary] = new XN[Salary] {
override def x2(m: Salary): Salary = m.copy(amount = m.amount * 2)
override def x3(m: Salary): Salary = m.copy(amount = m.amount * 3)
override def x4(m: Salary): Salary = m.copy(amount = m.amount * 4)
}
#2
object Salary extends XN[Salary] {
override def x2(m: Salary): Salary = new Salary(employee = m.employee, amount = m.amount * 2)
override def x3(m: Salary): Salary = new Salary(employee = m.employee, amount = m.amount * 3)
override def x4(m: Salary): Salary = new Salary(employee = m.employee, amount = m.amount * 4)
}
怎么做?
创建从 Salary 到 XN 的隐式转换可能是一个解决方案。这就是 scala 如何向现有 类 添加新功能而不扩展它们。
implicit def salary2XN(s: Salary): XN[Salary] = {
new XN[Salary] {
override def x2: Salary = Salary(s.employee, 2*s.amount)
override def x3: Salary = Salary(s.employee, 3*s.amount)
override def x4: Salary = Salary(s.employee, 4*s.amount)
}
}
[使用公认的解决方案,隐式是棘手的!]
greg 开了个好头,但正如所写,它不适用于您的解决方案。
这里有一些变化:
仍在使用:
case class Salary(employee: String, amount: Double) // As before
您可以在 Salary
上调用该方法或将其传递给 Salary
,您正在尝试同时执行这两项操作。
最简单的方法是尝试:
trait XN[M] {
def x2: M
def x3: M
def x4: M
}
implicit def salary2XN(s: Salary): XN[Salary] = {
new XN[Salary] {
override def x2: Salary = s.copy(amount = 2 * s.amount)
override def x3: Salary = s.copy(amount = 3 * s.amount)
override def x4: Salary = s.copy(amount = 4 * s.amount)
}
}
现在您可以使用您的签名调用每个方法:
Salary("bob", 200).x2
编辑:
使用普通旧扩展的解决方案:
trait XN[M] {
def x2: M
def x3: M
def x4: M
}
case class Salary(employee: String, amount: Double) extends XN[Salary] {
override def x2: Salary = Salary(employee, 2 * amount)
override def x3: Salary = Salary(employee, 3 * amount)
override def x4: Salary = Salary(employee, 4 * amount)
}
您现在可以用完全相同的方式调用它:
Salary("bob", 233).x2
注意:在以前的实现中,Salary
s 本身没有 XN
的方法,而是我们使用隐式转换将它们应用于每个 Salary。对于后一种实现,每个 Salary
都有 XN
的方法,我们在 case class
本身的实现中定义它。
因为 XN
似乎是一个 类型类 ,所以最好正确使用该模式而不是依赖 (气馁) 隐式转换.
trait XN[M] {
def x2(m: M): M
def x3(m: M): M
def x4(m: M): M
}
object XN {
object syntax {
implicit class XNOp[M](private val m: M) extends AnyVal {
@inline final def x2(implicit ev: XN[M]): M = ev.x2(m)
@inline final def x3(implicit ev: XN[M]): M = ev.x3(m)
@inline final def x4(implicit ev: XN[M]): M = ev.x4(m)
}
}
}
final case class Salary(employee: String, amount: Double)
object Salary {
implicit final val SalaryXN: XN[Salary] =
new XN[Salary] {
override def x2(s: Salary): Salary = s.copy(amount = s.amount * 2)
override def x3(s: Salary): Salary = s.copy(amount = s.amount * 3)
override def x4(s: Salary): Salary = s.copy(amount = s.amount * 4)
}
}
可以这样使用:
import XN.syntax._
val bobSalary = Salary("Bob", 100.0)
bobSalary.x2
// res: Salary = Salary("Bob", 200.0)
可以看到代码运行 here.
我有这个代码
case class Salary(employee: String, amount: Double){
}
trait XN[M] {
def x2(m: M): M
def x3(m: M): M
def x4(m: M): M
}
我想用 XN 特征扩展 Salary,以便进行以下测试:
test("Salary is extended with xN") {
val bobSalary = Salary("Bob", 100.0)
bobSalary.x2 shouldBe Salary("Bob", 200.0)
bobSalary.x3 shouldBe Salary("Bob", 300.0)
bobSalary.x4 shouldBe Salary("Bob", 400.0)
}
我的尝试:
#1
implicit val SalaryXN: XN[Salary] = new XN[Salary] {
override def x2(m: Salary): Salary = m.copy(amount = m.amount * 2)
override def x3(m: Salary): Salary = m.copy(amount = m.amount * 3)
override def x4(m: Salary): Salary = m.copy(amount = m.amount * 4)
}
#2
object Salary extends XN[Salary] {
override def x2(m: Salary): Salary = new Salary(employee = m.employee, amount = m.amount * 2)
override def x3(m: Salary): Salary = new Salary(employee = m.employee, amount = m.amount * 3)
override def x4(m: Salary): Salary = new Salary(employee = m.employee, amount = m.amount * 4)
}
怎么做?
创建从 Salary 到 XN 的隐式转换可能是一个解决方案。这就是 scala 如何向现有 类 添加新功能而不扩展它们。
implicit def salary2XN(s: Salary): XN[Salary] = {
new XN[Salary] {
override def x2: Salary = Salary(s.employee, 2*s.amount)
override def x3: Salary = Salary(s.employee, 3*s.amount)
override def x4: Salary = Salary(s.employee, 4*s.amount)
}
}
[使用公认的解决方案,隐式是棘手的!]
greg 开了个好头,但正如所写,它不适用于您的解决方案。
这里有一些变化:
仍在使用:
case class Salary(employee: String, amount: Double) // As before
您可以在 Salary
上调用该方法或将其传递给 Salary
,您正在尝试同时执行这两项操作。
最简单的方法是尝试:
trait XN[M] {
def x2: M
def x3: M
def x4: M
}
implicit def salary2XN(s: Salary): XN[Salary] = {
new XN[Salary] {
override def x2: Salary = s.copy(amount = 2 * s.amount)
override def x3: Salary = s.copy(amount = 3 * s.amount)
override def x4: Salary = s.copy(amount = 4 * s.amount)
}
}
现在您可以使用您的签名调用每个方法:
Salary("bob", 200).x2
编辑:
使用普通旧扩展的解决方案:
trait XN[M] {
def x2: M
def x3: M
def x4: M
}
case class Salary(employee: String, amount: Double) extends XN[Salary] {
override def x2: Salary = Salary(employee, 2 * amount)
override def x3: Salary = Salary(employee, 3 * amount)
override def x4: Salary = Salary(employee, 4 * amount)
}
您现在可以用完全相同的方式调用它:
Salary("bob", 233).x2
注意:在以前的实现中,Salary
s 本身没有 XN
的方法,而是我们使用隐式转换将它们应用于每个 Salary。对于后一种实现,每个 Salary
都有 XN
的方法,我们在 case class
本身的实现中定义它。
因为 XN
似乎是一个 类型类 ,所以最好正确使用该模式而不是依赖 (气馁) 隐式转换.
trait XN[M] {
def x2(m: M): M
def x3(m: M): M
def x4(m: M): M
}
object XN {
object syntax {
implicit class XNOp[M](private val m: M) extends AnyVal {
@inline final def x2(implicit ev: XN[M]): M = ev.x2(m)
@inline final def x3(implicit ev: XN[M]): M = ev.x3(m)
@inline final def x4(implicit ev: XN[M]): M = ev.x4(m)
}
}
}
final case class Salary(employee: String, amount: Double)
object Salary {
implicit final val SalaryXN: XN[Salary] =
new XN[Salary] {
override def x2(s: Salary): Salary = s.copy(amount = s.amount * 2)
override def x3(s: Salary): Salary = s.copy(amount = s.amount * 3)
override def x4(s: Salary): Salary = s.copy(amount = s.amount * 4)
}
}
可以这样使用:
import XN.syntax._
val bobSalary = Salary("Bob", 100.0)
bobSalary.x2
// res: Salary = Salary("Bob", 200.0)
可以看到代码运行 here.