从Java代码访问Scala Type类?

时间:2017-05-22 04:53:31

标签: java scala typeclass implicit

我使用类型类和ad-hoc多态在Scala中创建了许多不同的拍卖实现。

可以找到Scala实现的示例here

在Scala中,我创建了一个此次拍卖的实例,如下所示......

val google: GoogleStock = GoogleStock(tick=1)
val pricingRule = new MidPointPricingPolicy[GoogleStock]
val withDiscriminatoryPricing = OpenBidDoubleAuction.withDiscriminatoryPricing(pricingRule)

我希望用户能够从Java 8访问拍卖实现。

但我似乎无法弄清楚如何用Java创建拍卖实例。采取这种方法:

MidPointPricingPolicy<GoogleStock> midPointPricing = new MidPointPricingPolicy<GoogleStock>();
OpenBidDoubleAuction.DiscriminatoryPricingImpl<GoogleStock> auction = OpenBidDoubleAuction$.MODULE$.withDiscriminatoryPricing(midPointPricing);

有效,但没有类型类合同方法可用。具体做法是:

OpenBidDoubleAuction.DiscriminatoryPricingImpl<GoogleStock> auction2 = auction.insert(order3);

...产生以下编译错误。

Error:(90, 82) java: cannot find symbol
symbol:   method insert(org.economicsl.auctions.singleunit.orders.LimitAskOrder<org.economicsl.auctions.GoogleStock>)
location: variable auction of type org.economicsl.auctions.singleunit.twosided.SealedBidDoubleAuction.UniformPricingImpl<org.economicsl.auctions.GoogleStock>

在编译Java代码时,似乎Scala编译器为类型类生成的契约方法不可用。在我的build.sbt文件中,我设置了compileOrder := CompileOrder.ScalaThenJava,以确保首先编译这些Scala,以便这些方法可用。

根据@GhostCat的建议,我使用javap找出Scala编译器生成以下.class文件...

OpenBidDoubleAuction$DiscriminatoryPricingImpl$$anon$1.class

包含相关方法的字节码定义。

所以我想我需要知道如何从Java访问此字节代码文件中定义的内容?它甚至可能吗?

2 个答案:

答案 0 :(得分:3)

通用答案是:这是两种不同的语言。 java端唯一可见的内容是OpenBidDoubleAuction字节码中的元素。

因此:一种可能的方式来表示&#34;我可以从Java使用什么&#34;:转向javap并检查scalac生成的字节代码。这将告诉您所有可用的方法及其签名。如果你发现你的&#34;增强&#34;这个例子太复杂了:退后一步。创建一个 minimal 示例 - 一小段scala;然后仔细分析生成的字节代码。

当然:你首先检查documentation - 你要避免在一些根本不可能的事情上浪费你的时间。您可以从Java方面使用各种语言元素。

(请注意:该链接已过时,但可能已经足够作为您自己研究的起点)

答案 1 :(得分:1)

Java没有implicit关键字,也不知道任何关于implicits的内容。 Java implicit def只是另一种方法。因此,当您从Java调用此代码时,您必须显式添加所有隐式转换和隐式参数。如果你想知道它会是什么样子,你可以打开一个Scala REPL并使用//print <tab>提示来看看你的代码在几次desugarings之后会是什么样子并且明确暗示。

例如,给定一些类型Foo和隐式FooSyntax

scala> 42.foo //print <tab>
   FooSyntax[Int](42)(Foo.fooInt).foo // : String

要清楚,在<tab>显示的位置,您必须按Tab键而不是键入它:)

然后,如果你有点幸运,你所要做的就是将那些脱离了Scala的东西转换成实际的Java:

FooSyntax(42, Foo.fooInt()).foo();

如果你不太幸运,你可能需要添加一些额外的MODULE$内容。如果您甚至更少幸运,并且您必须与结构类型或交叉类型等内容进行互操作,那么您可能必须分别使用反射或转换。

但总的来说:如果要从Java调用相同的代码,则使用Scala的高级功能(如类型类)。如果你必须创建一个可以从Java调用的库,那么尝试在高级/不兼容的部分中编写(在Scala中)Java友好的包装器。