如何通过Java中的Scala通过包对象传递定义的隐式val

我正在使用Cats库.在Scala中,代码如下所示:

import cats.Semigroupal
import cats.instances.option._
val r = Semigroupal.tuple2(Option(1), Option(2))

元组2定义为:

def tuple2[F[_], A0, A1](f0:F[A0], f1:F[A1])(implicit semigroupal: Semigroupal[F], invariant: Invariant[F]):F[(A0, A1)]

实际上,以下隐式值既作为Semigroupal又作为Invariant传递(通过Intellij IDEA插件对Scala进行检查):

package cats
package instances

trait OptionInstances ...
  implicit val catsstdInstancesForOption: ...

如何通过Java代码在tuple2函数中传递catsstdInstancesForOption?

Semigroupal$.MODULE$.tuple2(
  Option.apply(1), Option.apply(2),
  ...,// and here?
  ... //here 
  );

依赖Cats库(如果需要):

<cats.core.version>1.5.0</cats.core.version>
...
<!-- https://mvnrepository.com/artifact/org.typelevel/cats-core -->
<dependency>
  <groupId>org.typelevel</groupId>
  <artifactId>cats-core_2.12</artifactId>
  <version>${cats.core.version}</version>
</dependency>

解决方法:

引用从Java的包对象内部定义的Scala对象是一件很痛苦的事,据我所知,没有充分的理由-完全是因为编译器决定修改名称的方式(例如,您不能直接引用cats .instances.package $option $(来自Java).

我以前想做这种事情,而我找到的最佳解决方案是这样的:

import cats.Apply;
import cats.Semigroupal$;
import cats.instances.OptionInstances;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import scala.Option;
import scala.Tuple2;

public class Test {
  public static Apply<Option> getoptionInstance() {
    try {
      Class<?> cls = Class.forName("cats.instances.package$option$");
      Field f = cls.getField("MODULE$");
      Method m = f.getType().getmethod("catsstdInstancesForOption");
      return (Apply<Option>) m.invoke(f.get(null));
    } catch (Exception e) {
      // Shouldn't happen but do something here anyway.
      return null;
    }
  }

  public static void main(String[] args) {
    Apply<Option> optionInstance = getoptionInstance();

    Option<Tuple2<Integer, Integer>> pair = Semigroupal$.MODULE$.tuple2(
      Option.apply(1),
      Option.apply(2),
      optionInstance,
      optionInstance
    );

    System.out.println(pair);
  }
}

太糟糕了,但是至少反射和投射被捆绑在一个地方.

如果您有很多需要从Java使用的实例,则可以从getoptionInstance中提取一些逻辑以减少重复,但这仍然不会很有趣.如果您可以在Scala端编写一些实用程序代码以从Java使用,那么制作一个对Java更友好的cat.instances并不难,只是不要使用包对象等.(为此我值得希望Cats在开发Java时更加关注Java友好性,但据我所知,没有人关心它.)

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...