试图扩展通用数组

时间:2010-07-01 14:56:42

标签: scala

我很确定在Scala中这很简单,但我似乎无法弄清楚类型系统需要做什么提示才能使其工作。

我希望有一个抽象的Printable类,然后隐式地将其他类转换为它。更具体地说,我想隐式地将Byte转换为Printable和Array [Byte]为Printable。

所以我做到了这一点:

abstract class Printable{
    def print():String
}
class PrintableByte(b:Byte) extends Printable{
    def print() = "" /*return something*/
}
implicit def printableByte(b:Byte) = new PrintableByte(b)

class PrintableArray(a:Array[Printable]) extends Printable{
    def print() = {
        for(i <- 0 until a.length) a(i).print()   // no problems here
        "" /*return something*/
    }
}
implicit def printableArray(a:Array[Printable]) = new PrintableArray(a)

然而:

val b:Byte = 0
b.print()   //no problem here
val a= new Array[Byte](1024)
a.print()   //error: value print() is not a member of Array[Byte]

我希望类型系统能够理解Array [Byte]隐式地是一个Array [Printable]并隐式地是一个Printable。

我错过了什么?

4 个答案:

答案 0 :(得分:6)

只是我的两分钱:

abstract class Printable{
    def print: String
}

class PrintableArray[T <% Printable](a: Array[T]) extends Printable{
    def print = (for(x <- a) yield x.print) mkString
}
implicit def printableArray[T <% Printable](a: Array[T]) = new PrintableArray(a)

class PrintableByte(b: Byte) extends Printable{
    def print = "%#02x" format b
}
implicit def printableByte(b:Byte) = new PrintableByte(b)

class PrintableInt(i: Int) extends Printable{
    def print = "%#08x" format i
}
implicit def printableInt(i: Int) = new PrintableInt(i)

然后:

scala> val b: Byte = -1
b: Byte = -1

scala> val i: Int = 100
i: Int = 100

scala> val bArr = Array[Byte](11,22,33,44)
bArr: Array[Byte] = Array(11, 22, 33, 44)

scala> val iArr = Array[Int](111111,222222,333333,444444)
iArr: Array[Int] = Array(111111, 222222, 333333, 444444)

scala> b print
res0: String = 0xff

scala> i print
res1: String = 0x000064

scala> bArr print
res2: String = 0xb0x160x210x2c

scala> iArr print
res3: String = 0x01b2070x03640e0x0516150x06c81c

scala>

答案 1 :(得分:3)

在这里解决我自己的问题,我需要的是一个视图绑定(对我来说是新的,仍在学习)在Array类型上,修改代码如下:

class PrintableArray[T <% Printable](a:Array[T]) {...}
implicit def printableArray[T <% Printable](a:Array[T]) {...}

这表明存在从类型T到Printable的隐式转换(视图),并且与执行此操作相同:

class PrintableArray[T](a:Array[T])(implicit t2printable: T => Printable) {...}
implicit def printableArray[T](a:Array[T])(implicit t2printable: T => Printable) {...}

不确定这是否是最好的方法,欢迎任何改进建议!

答案 2 :(得分:1)

a.print()进行类型检查,需要进行两次隐式转换,一次从BytePrintableByte,另一次从Array[PrintableByte]PrintableArray,但隐含不会以这种方式结合。为了使非类型检查表达式正确地进行类型检查,将只应用一个隐式转换。

答案 3 :(得分:0)

Randall已经说明了为什么你的代码不能按原样运行的原因。 在您的情况下,您可以按如下方式更改PrintableArray,然后按照您的描述(使用scala 2.8.0.RC7)工作:


abstract class Printable{
    def print():String
}
class PrintableByte(b:Byte) extends Printable{
    def print() = b.toString
}
implicit def printableByte(b:Byte) = new PrintableByte(b)

class PrintableArray(a:Array[Byte]) extends Printable {
    def print() = {
        var s:String = ""
        for(i <- 0 until a.length) s += a(i).print()
        s
    }
}
implicit def printableArray(a:Array[Byte]) = new PrintableArray(a)

scala> val a = new Array[Byte](10)
a: Array[Byte] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

scala> a print
res0: String = 0000000000