2010-07-02 5 views
8

Alle,Scala - wie explizit wählen, welche überladene Methode zu verwenden, wenn ein Argument null sein muss?

Ich mache einige Bildbearbeitung in Scala mit BufferedImages und Raster Objekte. Ich versuche, alle Pixel in dem gepufferten Bild mit dem folgenden Code zu erhalten.

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) 

Jetzt, wenn ich in relativ großen Dateien lese, funktioniert das gut. Wenn ich in 20x20 PNG-Dateien lesen, erhalte ich eine ArrayIndexOutOfBoundsException:

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

ich online gelesen habe, dass die Art und Weise, um dieses Problem die Pixelpuffer zu NICHT preallocate ist, sondern in einem Null-Wert zu übergeben und die man verwenden zurückgegeben von der Raster.getPixels-Methode.

Hier ist mein Problem. Als ich den naiven Ansatz tun und geben nur Nil als letztes Argument:

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

ich den Fehler

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) 

So offensichtlich der Compiler nicht, welche der beiden Methoden bestimmen kann ich anrufen bin versucht, ; es ist mehrdeutig. Wenn ich Java verwenden würde, würde ich die Null setzen, um meine Absicht explizit zu machen. Ich kann mir nicht vorstellen, wie ich in Scala den gleichen Effekt erzielen kann. Dinge, die ich habe versucht:

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 

Jede Idee, wie der Compiler explizit sagen, dass ich die Methode mit dem Int-Array als letzter Parameter anstelle einer Float-Array will?

EDIT: Wie eine Antwort darauf hinweist, bekam ich Nil mit Null vermischt. Nil ist eine leere Liste. Siehe die folgenden blog post

Auch sollte ich darauf hinweisen, dass die Array außerhalb der Grenzen Ausnahme war meine Schuld (wie diese Dinge oft sind). Das Problem war, ich nahm an, dass das Raster 3 Kanäle hatte, aber mein Bild hatte 4 Kanäle, da ich es so erstellt hatte. Ich preallocate stattdessen das Array wie folgt:

val numChannels = raster.getNumBands() 

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

Danke für die Hilfe

Antwort

15

(Angenommen, Sie wollen die Frage, wie Überlastungen zu lösen, wenn Sie eine Null übergeben müssen):

so wie man es in Java, durch den Typ der Überlastung entsprechende Zuschreibung Sie (in Java aufrufen wollen Sie würden werfen, aber es auf dasselbe: eine Behauptung des statischen Typs zum null) zuzuordnen:

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

Dies ist eine perfekte Erklärung. Thanks – I82Much

+6

Ich würde eher Sie erklärt haben, dass das Zuschreiben bedeutet, welchen der möglichen Typen Sie einen Wert annehmen möchten, während Gießen einen Wert in einen anderen Typ erzwingt, den es möglicherweise nicht nehmen kann oder nicht. –

5

Sie verwirrt Nil mit null.

+0

Ja, ich habe. - Guter Punkt. Wie ich in meinem Beitrag erwähne, half mir der folgende Beitrag: http://javaforyou.wordpress.com/2009/07/12/nothingness/ – I82Much

Verwandte Themen