我正在尝试将几个Java枚举值转换为另一个Java枚举(Scala Enumeration上的Java枚举的使用是由于遗留原因 - 枚举实际上是使用JAXB生成的)。
而不是简单的旧模式匹配并且将地图映射到另一个枚举类型,我认为编写类型类看起来更干净(也有点酷)。当我使用simulacrum来做这件事时,它编译并运行得非常好。但是,当我尝试自己手动编写类型类时,会抛出编译错误
[error] /Users/arun/IdeaProjects/AdvancedScala/src/main/scala/MultipleToSingleEnum.scala:32: value toEmail is not a member of TradeEnum
[error] println (TradeEnum.CLEARED.toEmail)
Java枚举的代码是:
来源枚举
public enum TradeEnum {
CONFIRMED, CLEARED
}
public enum SeriesEnum {
CREATED,DELETED
}
目标枚举
public enum EmailEnum {
T_CONFIRMED, T_CLEARED, S_CREATED, S_DELETED
}
使用Simulacrum的Typeclass(工作得很好!)
import simulacrum._
@typeclass trait EmailEnumConvertibleSim[A]{
def toEmailEnum(value:A):Option[EmailEnum]
}
object EmailEnumConvertibleSim{
implicit val tradeToEmailEnum = new EmailEnumConvertibleSim[TradeEnum]{
private val map=Map(
TradeEnum.CLEARED -> EmailEnum.T_CLEARED,
TradeEnum.CONFIRMED -> EmailEnum.T_CONFIRMED
)
override def toEmailEnum(value: TradeEnum): Option[EmailEnum] = map.get(value)
}
implicit val seriesToEmailEnum = new EmailEnumConvertibleSim[SeriesEnum]{
private val map=Map(
SeriesEnum.CREATED -> EmailEnum.S_CREATED,
SeriesEnum.DELETED -> EmailEnum.S_DELETED
)
override def toEmailEnum(value: SeriesEnum): Option[EmailEnum] = map.get(value)
}
}
import EmailEnumConvertibleSim.ops._
object MultipleToSingleEnumSim {
def main(args: Array[String]): Unit = {
println (TradeEnum.CLEARED.toEmailEnum)
}
}
手写类型类(Ops)
trait EmailEnumConvertible[A]{
def toEmailEnum(value:A):Option[EmailEnum]
}
object EmailEnumConvertible{
implicit val tradeToEmailEnum = new EmailEnumConvertible[TradeEnum]{
private val map=Map(
TradeEnum.CLEARED -> EmailEnum.T_CLEARED,
TradeEnum.CONFIRMED -> EmailEnum.T_CONFIRMED
)
override def toEmailEnum(value: TradeEnum): Option[EmailEnum] = map.get(value)
}
}
object EmailEnumOps{
implicit class EmailEnumOps[A] (value:A){
def toEmail()(implicit emailConvertable:EmailEnumConvertible[A]):Option[EmailEnum]={
emailConvertable.toEmailEnum(value)
}
}
}
import EmailEnumOps._
object MultipleToSingleEnum {
def main(args: Array[String]): Unit = {
println (TradeEnum.CLEARED.toEmail) //ERROR IS REPORTED HERE !!
}
}
对错误消息的任何启发都非常感谢。
答案 0 :(得分:1)
这是因为你的隐式类及其定义的对象都被称为trait EmailEnumConvertible[A]{
def toEmailEnum(value: A): Option[EmailEnum]
}
object EmailEnumConvertible{
implicit val tradeToEmailEnum: EmailEnumConvertible[TradeEnum] = new EmailEnumConvertible[TradeEnum]{
private val map = Map(
TradeEnum.CLEARED -> EmailEnum.T_CLEARED,
TradeEnum.CONFIRMED -> EmailEnum.T_CONFIRMED
)
override def toEmailEnum(value: TradeEnum): Option[EmailEnum] = map.get(value)
}
}
object AnyOtherName{
implicit class EmailEnumOps[A] (value: A){
def toEmail()(implicit emailConvertable:EmailEnumConvertible[A]): Option[EmailEnum]={
emailConvertable.toEmailEnum(value)
}
}
}
import AnyOtherName._
object MultipleToSingleEnum {
def main(args: Array[String]): Unit = {
println (TradeEnum.CLEARED.toEmail) // No error :-)
}
}
。
当您更改其工作对象的名称时:
scala> :paste
// Entering paste mode (ctrl-D to finish)
object A { def B(a: Int) = "foo" }
object B
import A._
B(4)
// Exiting paste mode, now interpreting.
<pastie>:41: error: B.type does not take parameters
B(4)
^
看起来当在当前作用域中定义对象然后导入具有相同名称的成员时,第一个对象仍然会隐藏导入的成员。
EmailEnumOps
隐式类EmailEnumOps
被编译为类EmailEnumOps
和隐式def EmailEnumOps._
。因此,当您导入TradeEnum.CLEARED
时,隐式def被对象遮蔽,因此@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
{{collaborators["0"]?.fullname}}
</div>
`,
})
export class App {
name:string;
collaborators: [{fullname: string}];
constructor() {
this.name = 'Angular2'
this.collaborators = [];
}
}
无法隐式转换。
此行为符合language specification:
中的规定不同类型的绑定在其上定义了优先级:
本地,继承或制作的定义和声明 可以通过package子句获得,也可以在同一个编译中定义 单位作为参考,具有最高优先权。
显式导入有 下一个最高优先级。
通配符导入次之 优先。
- 醇>
包子句提供的定义,但不是 也在与引用相同的编译单元中定义 最低优先级。