2011-07-08 69 views
4

我想知道如何在Scala中调用类型参数化方法时可能具有默认类型。假设我有以下方法某处:方法调用的默认类型

def apply[A](id: String)(implicit processor: Processor[A]) = 
    processor(data get id) 

我想AString,当编译器没有关于来推断哪种类型的提示。所以,我可以重载我的定义是:

def apply(id: String)(implicit processor: Processor[String]) = 
    processor(data get id) 

但删除后两种方法都会有相同的签名......有没有什么办法,以提供一个默认的类型?

回答

7

你可以通过定义下面的幻像t YPE:

sealed class DefaultsTo[A, B] 
trait LowPriorityDefaultsTo { 
    implicit def overrideDefault[A,B] = new DefaultsTo[A,B] 
} 
object DefaultsTo extends LowPriorityDefaultsTo { 
    implicit def default[B] = new DefaultsTo[B, B] 
} 

那么你的方法可以写成

def apply[A](id: String)(implicit e: A DefaultsTo String, 
            processor: Processor[A]) = 
    processor(data get id) 

overrideDefault保证,对于任何两个指定的类型,AB,编译器可以始终提供DefaultsTo[A, B]类型的对象的定义(例如DefaultsTo[Int, String])。然而,如果两种类型之一未指定(例如DefaultsTo[A, String]),编译器将优选识别这两种类型(在该示例中提供DefaultsTo[String, String],并因此推断出String为未指定类型A)。

作为Naftoli Gugenheim pointed out in this mailing list thread,还可以实现用一些漂亮的语法与语境范围:

class Has[B] { 
    type AsDefault[A] = A DefaultsTo B 
} 

def apply[A : Has[String]#AsDefault : Processor](id: String) = 
    implicitly[Processor[A]].apply(data get id) 
+1

请参阅[此问题](http://stackoverflow.com/questions/4403906/is-it-possible-in-scala-to-force-the-caller-to-specify-a-type-parameter-for-a相关技术。 –

0

在这种情况下,你可以使用一个小窍门

class C { 
    def apply[A](id: String) = (processor: Processor[A]) => id + processor 
    def apply(id: String)(implicit processor: Processor[String]) = id + processor 
} 

在更普遍的情况下,不知道SRY ...

编辑

我忘了你所需要的processor到是implicit所以它不会编译...

+0

如果他想编译器隐含提供处理器不工作。 –

+0

Yeap,只是注意到我自己,无论如何thx。 – agilesteel