2014-02-02 1 views
0

Является ли это правильным? Я в основном хочу выполнить определенный метод void.Использование лямбда для выполнения пустоты: Это правильно?

public abstract class Uniforms { 
    public static void setUniformMatrix4(final UniformLocation uniformLocation, final boolean transpose, final Matrix4f matrix4f) { 
     setUniformImpl(uniformLocation, u -> GL20.glUniformMatrix4(uniformLocation.getLocation(), transpose, matrix4f.asFloatBuffer())); 
    } 

    public static void setUniformMatrix4(final UniformLocation uniformLocation, final boolean transpose, final FloatBuffer matrix4fFloatBuffer) { 
     setUniformImpl(uniformLocation, u -> GL20.glUniformMatrix4(uniformLocation.getLocation(), transpose, matrix4fFloatBuffer)); 
    } 

    public static void setUniform(final UniformLocation uniformLocation, final float value) { 
     setUniformImpl(uniformLocation, u -> GL20.glUniform1f(uniformLocation.getLocation(), value)); 
    } 

    public static void setUniform(final UniformLocation uniformLocation, final int value) { 
     setUniformImpl(uniformLocation, u -> GL20.glUniform1i(uniformLocation.getLocation(), value)); 
    } 

    private static void setUniformImpl(final UniformLocation uniformLocation, final Consumer<UniformLocation> consumer) { 
     Program oldProgram = Program.getUsing(); 
     for (Program program : Program.getPrograms()) { 
      if (program.usesUniform(uniformLocation)) { 
       program.use(); 
       consumer.accept(uniformLocation); 
      } 
     } 
     if (oldProgram != null) { 
      oldProgram.use(); 
     }   
    } 
} 
+0

Да, это прекрасно, почему вы думаете, что есть проблема? – assylias

+0

@assylias Поскольку я не уверен, что именно так следует использовать lambdas, 'Consumer ' обычно потребляет 'T'. Однако в моем случае 'u' я передаю, не используется. Я мог бы подумать, что мне нужно что-то, что ничего не потребляет и ничего не производит? – skiwi

+0

@Downvoter: Пожалуйста, уточните, почему. – skiwi

ответ

2

Если ваша программа компилируется и дает вывод, который вы ожидаете, то в этом смысле это правильно. Однако это можно было бы прояснить.

Четыре общедоступных перегрузки все принимают параметр UniformLocation, который затем передается методу setUniformImpl. Затем этот метод вызывает потребителя и передает ему uniformLocation ... который затем игнорируется. Призывы к GL2.glUniform* методам в lambdas все захватuniformLocation вместо использования параметра u. Вы можете заменить Consumer на Runnable.

В качестве альтернативы, вы можете изменить тип Consumer к тому, что возвращаемое значение Uniform.getLocation() есть и извлечь каждый из этих вызовов в setUniformImpl и передать результат в качестве арг к consumer.accept. Это упростит ситуацию. У вас должно получиться что-то вроде:

public static void setUniform(final UniformLocation uniformLocation, final int value) { 
    setUniformImpl(uniformLocation, u -> GL20.glUniform1i(u, value)); 
} 

private static void setUniformImpl(final UniformLocation uniformLocation, final Consumer<Location> consumer) { 
    ... 
    consumer.accept(uniformLocation.getLocation()); 
    ... 
} 
+0

Я тоже думал о интерфейсе «Runnable», правильно ли было бы использовать в этом смысле? Насколько я знаю, это единственный интерфейс, в котором вы можете выполнять «методы». – skiwi

+1

Несомненно, 'Runnable' будет работать. Главное - «форма» функции, в смысле количества аргументов и возвращаемых значений. При выборе функционального интерфейса сначала просмотрите количество аргументов и возвращаемых значений и выберите подходящий интерфейс. (Возможно, специализировано для примитивов или логических элементов.) 'Runnable' принимает нулевые аргументы и возвращает void, поэтому, если это соответствует тому, что вы хотите,' Runnable' отлично работает. –

2

Если он скомпилирован, тогда проблем нет.

Давайте предположим, что метод ожидает:

void m(Consumer<SomeEvent> e); 

Тогда в Java 7 вы могли бы написать:

m(new Consumer<SomeEvent>() { void accept(SomeEvent e) { /* do nothing */ } }); 

где потребитель вы предоставите игнорирует аргумент e.

Аналогично, с лямбды, вы можете игнорировать аргументы и написать:

m(e -> { /* do nothing */ }); 
+0

@ Radiodef благодарит за исправление кода. – assylias

Смежные вопросы