Ссылки на методы, как в Java 8 в Scala

В этом классе Java:

import java.util.function.*;

public class T {

    public String func(String a) {
        System.out.println("There we go: " + a);
        return a;
        }

    public static void main(String... args) {
        final Supplier<T> c = T::new;
        final BiFunction<T, String, String> f = T::func;

        final T t = c.get();
        final String v = f.apply(t, "something");

        System.out.println(v);
    }

}

Я могу получить ссылку на метод конструктора T и на метод экземпляра func.

Есть ли способ сделать то же самое в scala, т.е. получить

val c: () => T = ??? // default constructor of T as function
val f: (T, String) => String = ??? // instance method func of T as function

не обертывая их так:

val c: () => T = () => new T
val f: (T, String) => String = (t, arg) => t.func(arg)

т. е. есть ли такой же элегантный способ, как способ Java 8, чтобы получить ссылки на конструктор и метод экземпляра для получения функций scala для этих вещей?


person scravy    schedule 03.11.2016    source источник
comment
Нет, вы не можете сделать это точно. Обычно тоже не нужно. Может быть, было бы более полезно, если бы вы объяснили, чего вы на самом деле пытаетесь достичь с помощью этого...   -  person Dima    schedule 03.11.2016
comment
В приведенном выше примере выражение final Supplier<T> c = T::new; семантически эквивалентно val c: () => T = () => new T. Не уверен, чего вы хотели бы избежать.   -  person maasg    schedule 03.11.2016


Ответы (2)


Во-первых, давайте посмотрим на дословный перевод кода Java на Scala:

class T {
  def func(a:String) : String = {
    println(s"There we go: $a")
    a
  }
}
object T {
  def main(args: Array[String]) = {
    val supplier = () => new T
    val f = (t:T) => t.func _

    val t = supplier()
    val v = f(t)("something")
    println(v)
  }
}

В Scala функции являются гражданами первого класса, поэтому нет необходимости иметь особые конструкции для «вещей, которые генерируют», как Java Supplier, поскольку она моделируется как функция: f: () => T (то же самое касается и ее аналога, Consumer как f: T => ())

Мы только что сказали, что функции являются гражданами первого класса, поэтому давайте посмотрим на версию вышеизложенного, используя эту парадигму:

object Tfunc {
  // let's remove the println side-effect from a function.
  val func: String => String = a => s"There we go: $a"

  def main(args: Array[String]) = {
    println(func("something"))
  }
}

В Scala нет аналога для получения ссылки на конструктор, но если целью является использование функционального подхода, Scala object предлагает простую конструкцию для хранения функций и не требует создания экземпляров.

person maasg    schedule 03.11.2016

Точно так же, как вы делаете в java 8, вы не можете. Для конструктора класса я думаю, что нет другого способа сделать это, кроме того, как вы это сделали.

Для функций вы можете использовать заполнители параметров, которые, на мой взгляд, «чище».

var t = new T()
var func = t.func _
func("a")

Если вы используете case class, вы можете использовать метод apply.

case class C(a: String)
var d = C.apply _
d("c")

Вы можете использовать функцию apply и для обычных классов, но вам придется реализовать ее самостоятельно. Для кейс-классов они реализуются автоматически.

person Tiago Engel    schedule 03.11.2016