Scala 未对Int执行隐式转换
在Scala中,我想为基本类型生成一些别名,然后通过类型类实现转换。这对我来说很有用,也是理解类型类的一个机会。代码如下:Scala 未对Int执行隐式转换,scala,typeclass,implicit,Scala,Typeclass,Implicit,在Scala中,我想为基本类型生成一些别名,然后通过类型类实现转换。这对我来说很有用,也是理解类型类的一个机会。代码如下: type Index = Int val Index = Int type Integer = Int val Integer = Int type Real = Double val Real = Double // to have companion object of Double also be the companion object of Real tra
type Index = Int
val Index = Int
type Integer = Int
val Integer = Int
type Real = Double
val Real = Double // to have companion object of Double also be the companion object of Real
trait Convertible[A] {
def toIndex(a: A): Index
def toInteger(a: A): Integer
def toReal(a: A): Real
}
implicit val ConvertibleIndex: Convertible[Index] = new Convertible[Index] {
def toIndex(i: Index) = i
def toInteger(i: Index) = i
def toReal(i: Index) = i.toDouble
}
implicit val ConvertibleInteger: Convertible[Integer] = new Convertible[Integer] {
def toIndex(i: Integer) = i
def toInteger(i: Integer) = i
def toReal(i: Integer) = i.toDouble
}
implicit val ConvertibleReal: Convertible[Real] = new Convertible[Real] {
def toIndex(r: Real) = r.toInt
def toInteger(r: Real) = r.toInt
def toReal(r: Real) = r
}
implicit val ConvertibleString: Convertible[String] = new Convertible[String] {
def toIndex(s: String) = s.toInt
def toInteger(s: String) = s.toInt
def toReal(s: String) = s.toDouble
}
implicit class ConvertibleSyntax[A](a: A)(implicit val c: Convertible[A]) {
def toIndex = c.toIndex(a)
def toInteger = c.toInteger(a)
def toReal = c.toReal(a)
}
现在考虑一下:
val a = 3.toReal
val b = 3.0.toReal
val c = "3".toReal
a
的语句未编译,编译错误为:方法toReal不是Int
的成员。但是,对于b
和c
语句,到ConvertibleSyntax
的隐式转换是正确的
为什么隐式转换不适用于
Int
,而适用于Double
和String
?,因为您为索引和整数定义了不明确的隐式(Int
)
编译器应该选择哪一个?,因为您为索引
和整数
(都是Int
)定义了不明确的隐式
编译器应该选择哪一个?我想您可能对Scala如何进行隐式转换有点困惑。(一个常见的错误是隐式有点过度使用。)
我认为您首先需要的是一个隐式转换函数,甚至是一个隐式类。以下是如何使用后一种方法实现这一点:
注意:Int
、Index
和Integer
被同等对待,Real
和Double
也是如此,这在一定程度上混淆了问题,所以我将其简化为一些可行的方法。而且,Convertible
不需要是泛型的,因为它的转换函数不需要参数。最后,您不应该为您的类型同时声明type
和val
类型索引=Int
整型=Int
类型Real=Double
性状转换{
def toIndex:索引
def toInteger:整数
真的吗
}
//隐式类不能在顶级作用域中定义,因此它们属于对象。
对象隐式{
隐式类可转换元素(i:Int)
延伸敞篷车{
覆盖def toIndex=i
覆盖def toInteger=i
覆盖def toReal=i.toDouble
}
隐式类ConvertibleDouble(d:Double)
延伸敞篷车{
覆盖def toIndex=d.toInt
覆盖def toInteger=d.toInt
覆盖def toReal=d
}
隐式类可转换字符串(s:String)
延伸敞篷车{
覆盖def toIndex=s.toInt
覆盖def toInteger=s.toInt
覆盖def toReal=s.toDouble
}
}
现在试试这个:
importimplicits_
val a=3.5升
val b=3.0.t真实值
val c=“3”toReal
这里发生了什么事?嗯,隐式类
声明定义了用附加函数修饰唯一构造函数参数的类。如果编译器发现您正试图对一个没有该方法的类型调用一个方法,它将查看是否在范围内对一个有该方法的类型进行了隐式转换。如果是,则使用它并调用该函数;如果不是,则会出现编译器错误。(import
语句用于将类引入当前范围。)
因此,例如,当编译器看到“3.toReal
时,它首先确定“3”
是字符串。由于此类型没有.toReal
成员,因此它尝试查找从字符串
到具有此成员的类型的转换。它查找接受字符串
参数并提供.toReal
方法的可转换字符串
隐式类。耶!因此,编译器通过将“3”
传递给ConvertibleString
的构造函数来创建此类的实例,然后对结果调用.toReal
另一方面,当implicit
与值一起使用时,它会告诉编译器该值是未提供的相同类型的任何匹配隐式参数的默认值切勿将implicit
与基元或公共库类型一起使用强>
例如:
最终案例类示例(i:Int)
//默认。
隐式val name canbeanythingatall=示例(5)
//具有隐式参数的函数。
def someFunc(隐式x:示例):单位=println(s“值为$x”)
现在,如果你这样写:
someFunc
输出将是值为示例(5)
隐式
值和参数是一个高级主题,我现在不担心它们是如何使用的。我想您可能对Scala如何进行隐式转换有点困惑。(一个常见的错误是隐式有点过度使用。)
我认为您首先需要的是一个隐式转换函数,甚至是一个隐式类。以下是如何使用后一种方法实现这一点:
注意:Int
、Index
和Integer
被同等对待,Real
和Double
也是如此,这在一定程度上混淆了问题,所以我将其简化为一些可行的方法。而且,Convertible
不需要是泛型的,因为它的转换函数不需要参数。最后,您不应该为您的类型同时声明type
和val
类型索引=Int
整型=Int
类型Real=Double
性状转换{
def toIndex:索引
def toInteger:整数
真的吗
}
//隐式类不能在顶级作用域中定义,因此它们属于对象。
对象隐式{
隐式类可转换元素(i:Int)
延伸敞篷车{
覆盖def toIndex=i
覆盖def toInteger=i
覆盖def toReal=i.toDouble
}
隐式类ConvertibleDouble(d:Double)
延伸敞篷车{
覆盖def toIndex=d.toInt
覆盖def toInteger=d.toInt
覆盖def toReal=d
}
隐式类可转换限制: