这是“幻影类型”的精确转换吗?在Java?

时间:2015-01-10 11:57:07

标签: java scala phantom-types

这是Scala' Phantom Type'演示显示compile-time checking of Rocket Launch configuration

object RocketModule {

   sealed trait NoFuel
   sealed trait Fueled
   sealed trait NoO2
   sealed trait HasO2

   final case class Rocket[Fuel, O2] private[RocketModule]()

   def createRocket = Rocket[NoFuel, NoO2]()

   def addFuel[O2](x : Rocket[NoFuel, O2]) = Rocket[Fueled, O2]()

   def addO2[Fuel](x : Rocket[Fuel, NoO2]) = Rocket[Fuel, HasO2]()

   def launch(x : Rocket[Fueled, HasO2]) = "blastoff"

   implicit def toPiped[V] (value:V) = new {
      def |>[R] (f : V => R) = f(value)
   }
   //Create a rocket, fuel it, add o2, then launch it
   def test1 = createRocket |> addFuel |> addO2 |> launch

   //This compiles just fine, too.  It doesn't matter which order we put in the fuel and o2
   def test2 = createRocket |> addO2 |> addFuel |> launch

   //This won't compile - there's no fuel
   def test3 = createRocket |> addO2 |> launch

   // This won't compile either - there's no o2
   def test4 = createRocket |> addFuel |> launch

   // This won't compile because you can't add fuel twice
   def test5 = createRocket |> addFuel |> addO2 |> addFuel |> launch
}

我试图将其转换为Java等价物。

package com.example;

public class RocketModule {


    public static NoFuelNoO2Rocket createRocket() {return new NoFuelNoO2Rocket() {};}

    public static void launch(HasFuelHasO2Rocket rocket) {System.out.println("Launch");}

    private static NoFuelHasO2Rocket addO2(NoFuelNoO2Rocket rocket) {return rocket.addO2();}

    private static HasFuelHasO2Rocket addO2(HasFuelNoO2Rocket rocket) {return rocket.addO2();}

    private static HasFuelNoO2Rocket addFuel(NoFuelNoO2Rocket rocket) {return rocket.addFuel();}

    private static HasFuelHasO2Rocket addFuel(NoFuelHasO2Rocket rocket) {return rocket.addFuel();}

    public static void main(String args[]) {
        //test1
        launch(addFuel(addO2(createRocket())));

        //test2
        launch(addO2(addFuel(createRocket())));

        //test3 - won't compile - no Fuel
        //launch(addO2(createRocket()));

        //test4 - won't compile - no O2
        //launch(addFuel(createRocket()));

        //test5 - won't compile - can't add fuel twice
        //launch(addFuel(addO2(addFuel(createRocket()))));

    }
}

class NoFuelNoO2Rocket  {
    public NoFuelHasO2Rocket addO2() {return new NoFuelHasO2Rocket();}

    public HasFuelNoO2Rocket addFuel() {return new HasFuelNoO2Rocket();}
}

class HasFuelNoO2Rocket {
    public HasFuelHasO2Rocket addO2() {return new HasFuelHasO2Rocket();}
}

class NoFuelHasO2Rocket  {
    public HasFuelHasO2Rocket addFuel() {return new HasFuelHasO2Rocket();}
}

class HasFuelHasO2Rocket  {}

我的问题是:这是“幻影类型”的准确转换吗?在Java?

1 个答案:

答案 0 :(得分:2)

您似乎可以直接将Scala示例翻译为Java:

interface Fueled {}
interface NoFuel {}
interface HasO2 {}
interface NoO2 {}

class Rocket<Fuel, O2> {}

public class PhantomJava {
    public static Rocket<NoFuel, NoO2> createRocket() { return new Rocket<NoFuel, NoO2>(); }    
    public static void launch(Rocket<Fueled, HasO2> rocket) { System.out.println("Launch"); }   
    private static <Fuel> Rocket<Fuel, HasO2> addO2(Rocket<Fuel, NoO2> rocket) { return new Rocket<Fuel, HasO2>(); }    
    private static <O2> Rocket<Fueled, O2> addFuel(Rocket<NoFuel, O2> rocket) { return new Rocket<Fueled, O2>(); }

    public static void main(String args[]) {
        // test1
        launch(addFuel(addO2(createRocket())));
        // test2
        launch(addO2(addFuel(createRocket())));
        // test3 - won't compile - no Fuel
        // launch(addO2(createRocket()));
        // test4 - won't compile - no O2
        // launch(addFuel(createRocket()));
        // test5 - won't compile - can't add fuel twice
        // launch(addFuel(addO2(addFuel(createRocket()))));
    }
}

此外,您应该在Scala和Java代码中添加一些类型约束。

Scala的:

  sealed trait FuelStatus
  sealed trait NoFuel extends FuelStatus
  sealed trait Fueled extends FuelStatus
  sealed trait O2Status
  sealed trait NoO2 extends O2Status
  sealed trait HasO2 extends O2Status

  final case class Rocket[Fuel <: FuelStatus, O2 <: O2Status] private[PhantomScala]()

  def addFuel[O2 <: O2Status](x : Rocket[NoFuel, O2]) = Rocket[Fueled, O2]()
  def addO2[Fuel <: FuelStatus](x : Rocket[Fuel, NoO2]) = Rocket[Fuel, HasO2]()

爪哇:

interface FuelStatus {}
interface Fueled extends FuelStatus {}
interface NoFuel extends FuelStatus {}
interface O2Status {}
interface HasO2 extends O2Status {}
interface NoO2 extends O2Status {}

class Rocket<Fuel extends FuelStatus, O2 extends O2Status> {}

...

    private static <Fuel extends FuelStatus> Rocket<Fuel, HasO2> addO2(Rocket<Fuel, NoO2> rocket) { return new Rocket<Fuel, HasO2>(); }
    private static <O2 extends O2Status> Rocket<Fueled, O2> addFuel(Rocket<NoFuel, O2> rocket) { return new Rocket<Fueled, O2>(); }