2011-09-03 72 views
2

我尝试在类型A已经固定Int一个子类覆盖此方法如果通用类型已经修复,如何用隐式参数覆盖泛型方法?

def sum[B >: A](implicit num: Numeric[B]): B = ... 

我已经尝试过

override def sum: Int = ... 

但这并不覆盖,当然,导致了不同的方法解析基于在运行时动态类型。

进一步说,

def sum[B >: Int](implicit num: Numeric[B]): Int 

不覆盖,而

def sum[B >: Int](implicit num: Numeric[Int]): Int 

不,还有

def sum(implicit num: Numeric[Int]): Int 

为什么是这样呢?是否有可能摆脱多余的限制B

我不确定哪些类型和implicits我可以省略和什么必须留,以便该方法仍然覆盖。

回答

2

好吧,试图解释为什么规则必须迫使你保持签名与隐含参数和方差。首先,一个不明确的参数仍然是一个参数,它可以被明确地传递,除了可能当它有一个单例类型(这不会很有用)时,它的几个不同的实例是可能的。

假设我创建

case class ZModulo(val p: Int) extends Numeric[Int] { 
    def plus(a: Int, b: Int) = (a+b) % p 
    // others along the same line 
} 

这似乎是一个合适的NumericNumeric文档没有说明哪些法律应该预期,但ZModulo并非不合理。

现在有你的

class Summable[A] { 
    def sum[B >: A](implicit num: Numeric[A]): B =... 
} 

如果我有val ints : Summable[Int],我当然可以调用ints.Sum(ZModulo(3))。所以如果你的班级是Summable[Int]的子类,它必须允许我这样做。所以你不能删除Numeric参数。

其次,假设我来一个Numeric[Any]。不知道我该如何合理地为数字做,但规范和编译器不知道。无论如何,他们也必须接受不合理的实施。因此,让我们

object MixThemAll : Numeric[A] {...} 

于累加签名允许ints.sum(MixThemAll)。所以你的子类也必须允许。

因此,让您删除子类中的隐式参数或方差将是不健全的。

+0

的确如此。我觉得有趣的是,即使情况很好(在我的答案中,类别'C2扩展了C1'和'D2扩展了D1'),它仍然是*非法改变签名。 –

+0

在D上,我认为你是对的,原因是它会使超载的规则变得糟糕。在C上,我不知道。你甚至可以考虑一个通用结果被非泛型下界替代。但是,编写泛型参数没有不良后果。所以也许它不配有一个特别的规则来允许这样做? –

3

第一个问题是重写的方法需要相同数量和类型的参数,即使它们未被使用。例如,

class C1 { 
    def f[B] = println("hello") 
} 

class C2 extends C1 { 
    override def f = println("world") // Error: f overrides nothing (needs parameter B) 
} 

除此之外,还有还有,因为Numeric[A]与健全的一个问题是在A不变。这意味着只要BC不同,就不存在Numeric[B]Numeric[C]之间的子类型关系。

想象Numeric是一个适当的方差的特点,它仍然不会工作;显然,中覆盖的方法签名必须是完全一样的:

class D1 { 
    def g(x: Int) {} 
} 

class D2 extends D1 { 
    override def g(x: Any) {} // Error: g overrides nothing (different parameter type) 
} 

我不知道为什么重载方法的类型不能被扩大。 编辑:原因或许是超载的兼容性,如

class D1 { 
    def g(x: Any) {} 
    def g(x: Int) {} // This is legal, even though the definitions seem to overlap 
} 

总之,当你重写,必须保留方法的签名,包括类型参数。在你的情况,这是你能做的最好的:

override def sum[B >: Int](implicit num: Numeric[B]): B = ... 
+0

那么我的方法应该如何呢? – soc

+0

你需要编译的版本是关于你能做的最好的版本。 –

相关问题