2016-09-24 82 views
3

我最近开始学习Scala的隐式“魔术”,我遇到了隐式Scala对象的麻烦。我试过所有可能的变体,但似乎没有任何工作。无法找到参数的隐式值

让我们假设我有一个像这样的类,其中有一些solve()函数。如果输入a,b是Float,它应该返回2个Float值。否则,它应该返回另一种类型的值:

class Solver[T](val a: T, val b: T) { 
    def solve[A](implicit num: customNumeric[T]): Option[(T, T)] = { 
     Option(
      num.f(num.g(a)), 
      num.f(num.g(b))) 
    } 
} 

假设另一种类型的值是类的一个对象是这样的:

class MyClass[T] (x: T, y: T)(implicit num: customNumeric[T]) { 
    val field : T = num.f(x) 
} 

而且,我们还假设我没有我需要的功能基本的斯卡拉数字,所以我应该做我自己的自定义数字。

这里是我做了什么:

我做我自己的customNumeric一个抽象类,用我的方法F()和G()和几个扩展我的customNumeric一些值类型的隐式对象(整型,浮点为例),并在其中实现的方法:

abstract class customNumeric[T] { 
    def f(x: T): T 
    def g(x: T): T 
} 

object customNumeric { 
    implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]] { 
     def f(x: MyClass[Int]) = new MyClass[Int](x.field + 5) 
     def g(x: MyClass[Int]) = new MyClass[Int](x.field - 5) 
    } 
    implicit object FloatIsCustomNumeric extends customNumeric[Float] { 
     def f(x: Float): Float = x + 3 
     def g(x: Float): Float = x - 3 
    } 
} 

在我看来求解的解决()应使用隐customNumeric对象来获得)基于类型的求解器的输入值的参考内解决(方法的实现。

但是,这并不如编译器工作说:

could not find implicit value for parameter num: customNumeric[Int] 
     def f... 

还抱怨,因为在同一行没有足够的参数的构造函数MyClass

我已经试图使伴侣对象投IntMyClass

object Fraction { 
    implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1) 
} 

但也doen't似乎工作。我试图让另一个隐式对象来实现我在customNumeric [MyClass [Int]]中使用的方法。

你有什么想法吗?提前致谢!

回答

2

问题是,你正试图用本身需要同一个隐式对象的类来定义隐式对象。

含义,这样的:

class MyClass[T] (x: T, y: T)(implicit num: CustomNumeric[T]) 

需要一个隐含的CustomNumeric[T]的存在。使用该类型不能定义IntIsCustomNumeric

implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]] 

当你实现IntIsCustomNumeric,你需要实现它Int类型,而不是MyClass[Int]类型。当你这样做时,我。E:

object CustomNumeric { 
    implicit object IntIsCustomNumeric extends CustomNumeric[Int] { 
    override def f(x: Int): Int = x 
    override def g(x: Int): Int = x 
    } 
} 

现在,你可以创建一个Solver[Int]这需要一个隐含的CustomNumeric[Int]

def main(args: Array[String]): Unit = { 
    import CustomNumeric._ 

    val solver = new Solver[Int](1, 2) 
    println(solver.solve) 
} 

现在,它也更容易创建从Int类型的东西,创建MyClass[Int]的隐式转换:

implicit object MyClassIsCustomNumeric extends CustomNumeric[MyClass[Int]] { 
    override def f(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 5) 
    override def g(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 3) 
} 

implicit def intToMyClass(i: Int) = new MyClass[Int](i) 
+0

感谢您的详细解答!我认为我明白了'Solver'将使用'IntIsCustomNumeric'对象,然后通过'intToMyClass'强制转换方法将它隐式转换为'MyClass'(它具有方法实现)。但是试图调试这个强制转换的执行让我想到编译器知道'IntIsCN'应该被转换为'MyClassIsCN',因为'IntIsCN'具有完整的方法实现。所以它可以只使用'IntIsCN'的方法来执行所有的操作。还有一个问题 - 如果'f(x:Int)'不返回'Int' –

0

你觉得这个怎么样

object customNumeric { 

    implicit object IntIsCustomNumeric extends customNumeric[Int] { 
    def f(x: Int): Int = x + 3 

    def g(x: Int): Int = x - 3 
    } 

    implicit object FloatIsCustomNumeric extends customNumeric[Float] { 
    def f(x: Float): Float = x + 3 

    def g(x: Float): Float = x - 3 
    } 

    implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1) 

    implicit object cn extends customNumeric[MyClass[Int]] { 
    def f(x: MyClass[Int]) = x.field + 5 

    def g(x: MyClass[Int]) = x.field - 5 
    } 

} 
相关问题