2013-03-31 48 views
9

我正在更新我的2.9。*项目到2.10。我有几个类的基本类型(角度,长度等),看起来像他们是价值类型的完美候选人。不幸的是,我使用这些类型的Java代码不是编译的,我无法弄清楚为什么。我已经将它简化为一组非常简单的代码。任何建议将不胜感激。使用Scala 2.10.1 Java中的值类型

角类定义(斯卡拉)

package com.example.units 

class Angle(val radians : Double) extends AnyVal 
{ 
    def degrees = radians * 180.0/math.Pi 
} 

object Angle 
{ 
    val Zero = new Angle(0) 
} 

角测试案例(痛苦地用Java编写的)

package com.example.units; 

import junit.framework.Assert; 
import org.junit.Test; 

public class AngleTest 
{ 
    @Test 
    public static void TestZero() 
    { 
     Angle a = Angle.Zero(); 
     Assert.assertEquals(a.degrees(), 0, 1E-9); 

    } 

} 

当我编译,我得到这个错误:

AngleTest.java:19 incompatible types 
found :double 
required: com.example.units.Angle 
Angle a = Angle.Zero(); 

      ^

它看起来对我来说,就好像Angle.Zero以双倍而非角度的形式返回。我尝试添加box/unbox方法,但仍然收到相同的错误。再次,任何帮助将不胜感激。

回答

10

Scala编译器将值类转换为unboxed类型,从而消除了运行时的代价。检查编译后的class文件为Angle,你会看到:

public static double Zero(); 

所以从Java的角度来看,Angle.Zero返回一个double;它没有意识到Scala的值类的语义。

角度的自己的方法,如degrees,被编译成)一个静态的扩展,需要在拆箱值(double法)B)的实例方法:这意味着后者仍然可以

public static double degrees$extension(double); 
public double degrees(); 

在Java中调用Angle的实例:

Angle a = new Angle(0); 
Assert.assertEquals(a.degrees(), 0, 1E-9); 
+0

感谢您的回复。我在我的伴侣类(Angle.fromDegrees(),Angle.fromRadians()等)中使用了很多工厂方法,以提高可读性。现在所有这些方法都有与上面所述相同的问题。在我看来,应该有一种方法来完成这项工作。 – fbl

+1

我非常想知道如何让它工作。尝试了几个解决方法之后,没有什么东西看起来很优雅了(例如,在Java测试中,您可以将从.Zero()调用接收到的值包装在一个Angle中,但会降低可读性)。我认为这里的根本原因在于Scala的值类并不是为了与普通类相同的Java互操作性而设计的;它们只是一个编译时抽象来简化您的Scala代码。我建议在你的案例中使用正规课程。 –

+0

不幸的是,我得出了同样的结论。如果这不是一个bug,那么它至少是一个设计缺陷w /值类型。斯卡拉的优势之一是它本身具有Java代码的互操作能力。我会避免使用它们,直到它被解决。 – fbl