2010-07-02 9 views
8

Todos,Scala: ¿cómo elegir explícitamente qué método sobrecargado utilizar cuando un argumento debe ser nulo?

Estoy haciendo algo de manipulación de imágenes en Scala haciendo uso de imágenes BufferedImages y objetos Raster. Estoy intentando obtener todos los píxeles en la imagen almacenada en el búfer con el siguiente código.

val raster = f.getRaster() 

// Preallocating the array causes ArrayIndexOutOfBoundsException .. http://forums.sun.com/thread.jspa?threadID=5297789 
// RGB channels; 
val pixelBuffer = new Array[Int](width*height*3) 
val pixels = raster.getPixels(0,0,width,height,pixelBuffer) 

Ahora, cuando leo en archivos relativamente grandes, esto funciona bien. Cuando leí en 20x20 archivos PNG, consigo un ArrayIndexOutOfBoundsException:

java.lang.ArrayIndexOutOfBoundsException: 1200 
at sun.awt.image.ByteInterleavedRaster.getPixels(ByteInterleavedRaster.java:1050) 

He leído online que la forma de evitar este problema es no asignar previamente la pixelBuffer, pero en lugar de pasar de un valor nulo y el uso de la devuelto por el método Raster.getPixels.

Aquí está mi problema. Cuando hago el enfoque ingenuo y sólo tiene que pasar Cero como último argumento:

val pixels = raster.getPixels(0,0,width,height,Nil) 

consigo el error

error: overloaded method value getPixels with alternatives (Int,Int,Int,Int,Array[Double])Array[Double] <and> (Int,Int,Int,Int,Array[Float])Array[Float] <and> (Int,Int,Int,Int,Array[Int])Array[Int] cannot be applied to (Int,Int,Int,Int,Nil.type) 
val pixels = raster.getPixels(0,0,width,height,Nil) 

Así que, obviamente, el compilador no puede determinar cuál de los dos métodos que estoy tratando de llamar ; es ambiguo Si estuviera usando Java, lanzaría el nulo para que mi intención sea explícita. No puedo entender cómo obtener el mismo efecto en Scala. Cosas que he intentado:

val pixelBuffer:Array[Int] = Nil // Cannot instantiate an Array to Nil for some reason 
Nil.asInstanceOf(Array[Int]) // asInstanceOf is not a member of Nil 

alguna idea de cómo decirle al compilador explícitamente que quiero que el método de la matriz Int como último parámetro en lugar de una red de flotadores?

EDITAR: Como una respuesta señala, Nil estaba confundido con nulo. Nil es una lista vacía. Consulte el siguiente blog post

Además, debo señalar que la excepción fuera de límites de la matriz fue mi culpa (ya que estas cosas a menudo lo son). El problema fue que asumí que el ráster tenía 3 canales, pero mi imagen tenía 4 canales, ya que lo había creado de esa manera. Yo en cambio asignar previamente la matriz de la siguiente manera:

val numChannels = raster.getNumBands() 

val pixelBuffer = new Array[Int](width*height*numChannels) 
val pixels = raster.getPixels(minX,minY,width,height,pixelBuffer) 

Gracias por la ayuda

Respuesta

15

(Asumiendo que desea que la cuestión de cómo resolver sobrecargas cuando se necesita para pasar un nulo):

Tal como lo haría en Java, por atribuir el tipo correspondiente a la sobrecarga que desea invocar (en Java que había lanzado, pero viene a ser lo mismo: una afirmación de tipo estático para asignar a la null):

scala> object O { def m(i: Int, s: String): String = s * i; def m(i: Int, l: List[String]): String = l.mkString(":") * i } 
defined module O 

scala> O.m(23, null) 
<console>:7: error: ambiguous reference to overloaded definition, 
both method m in object O of type (i: Int,l: List[String])String 
and method m in object O of type (i: Int,s: String)String 
match argument types (Int,Null) 
     O.m(23, null) 
     ^

scala> O.m(23, null: String) 
res4: String = nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull 

scala> O.m(23, null: List[String]) 
java.lang.NullPointerException 
     at O$.m(<console>:5) 
     at .<init>(<console>:7) 
     at .<clinit>(<console>) 
     at RequestResult$.<init>(<console>:9) 
     at RequestResult$.<clinit>(<console>) 
     at RequestResult$scala_repl_result(<console>) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981) 
     at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981) 
     at scala.util.control.Exception$Catch.apply(Exception.scala:7... 
scala> 
+0

Esta es una explicación perfecta. Gracias – I82Much

+6

Preferiría que me explicaras que atribuir significa elegir cuál de los posibles tipos quieres que asuma un valor, mientras que el lanzamiento fuerza un valor en otro tipo, que puede o no tomarse. –

5

confundido con Nilnull.

+0

sí lo hice. - Buen punto. Como mencioné en mi edición, la siguiente publicación me ayudó a resolverlo: http://javaforyou.wordpress.com/2009/07/12/nothingness/ – I82Much

Cuestiones relacionadas