2013-03-31 96 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