Scala - как явно выбрать, какой перегруженный метод использовать, когда один аргумент должен быть нулевым?

голоса
8

Все,

Я делаю некоторые манипуляции с изображениями в Scala путем использования BufferedImages и растровых объектов. Я пытаюсь получить все пиксели в буферном изображение со следующим кодом.

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)

Теперь, когда я прочитал в относительно больших файлов, это работает отлично. Когда я прочитал в 20x20 PNG файлов, я получаю ArrayIndexOutOfBoundsException:

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

Я прочитал в Интернете , что способ обойти эту проблему, чтобы не заранее выделить в pixelBuffer, но вместо того, чтобы перейти в нулевом значении и использовать один возвращенный метод Raster.getPixels.

Вот моя проблема. Когда я наивный подход и просто передать Nil в качестве последнего аргумента:

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

Я получаю ошибку

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)

Так, очевидно, что компилятор не может определить, какой из двух методов, я пытаюсь позвонить; это неоднозначно. Если бы я использовал Java, я бы бросил нуль, чтобы сделать мое намерение явным. Я не могу вполне понять, как получить тот же эффект в Scala. Вещи, которые я пробовал:

 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

Любая идея, как сообщить компилятору явно, что я хочу, метод с массивом Int в качестве последнего параметра, а не массив Float?

EDIT: Как ответ указывает, что я получаю Nil вперемешку с нулем. Ноль является пустым списком. Смотрите следующий блог

Кроме того, я должен отметить, что массив из исключения ограничивающих был моя вина (так как эти вещи часто). Проблема заключалась в том, я предполагал, что растр было 3 канала, но мое изображение было 4 канала, так как я создал его таким образом. Вместо этого я заранее выделить массив следующим образом:

val numChannels = raster.getNumBands() 

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

Спасибо за помощь

Задан 02/07/2010 в 22:02
источник пользователем
На других языках...                            


2 ответов

голоса
16

(Предположим, что вы хотите, вопрос о том, как решить перегрузки, когда вам нужно передать нулевое):

Так же , как вы бы в Java, приписывая тип , соответствующий перегрузки вы хотите вызвать (в Java вы бы бросить, но это одно и то же: утверждение статического типа для назначения на 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>
Ответил 02/07/2010 в 22:16
источник пользователем

голоса
5

Вы путать Nilс null.

Ответил 02/07/2010 в 22:06
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more