2011-11-12 143 views
2

说我有两个类具有相同标识符的参数化类型斯卡拉:抽象类型和混入

trait A { 
    type O 
    def f(a: Int, os: Seq[O]): Int 
    } 

    trait B { 
    type O 
    def g(a: Int, o: O): Int = { h1(o) + h2(a) } 
    def h1(o: O): Int 
    def h2(a: Int): Int = {a/2} 
    } 

我想创建一个子类,将“嫁”两

trait C extends A with B { 
    def f(a: Int, os: Seq[O]): Int = { 
     os.map{ o => g(a, o) }.sum 
    } 
    } 

最后,我建立了C

class D extends C { 
    type O = Int 
    def h1(o: O): Int = {5 * o} 
    } 

的执行情况的书面C我不ÿ等知道是什么类型的O - 不过,我想限制A.O == B.O,使得“有意义”在A.f实现使用B.g。我试图实现这一点,它令人惊讶的好像斯卡拉认为,只有过一个type O

val d = new D 
    println(d.f(1, Seq(1,2,3))) 

对我来说,这似乎是不正确 - 为什么要A.OB.O同意吗?

编辑 我也想指出,如果你是不是把约束O对像这样,

case class Z() 
    case class Z1() extends Z 
    case class Z2() extends Z1 

    trait A { 
    type O <: Z 
    } 

    trait B { 
    type O >: Z2 
    } 


class D extends C { 
    type O = Z1 

编译失败。但是,如果你把这个,而不是,

trait A { 
    type O <: Z 
    } 

    trait B { 
    type O <: Z1 
    } 
    class D extends C { 
    type O = Z2 

编译成功,一切运行良好。

回答

4

我认为斯卡拉总是“结婚”的成员 - 无论是类型和值的成员 - 性状两者混合时:

trait A { type T = Int } 
trait B { type T = String } 

object C extends A with B 

给出性状A

压倒一切的T型,等于Int; 类型T的性状B,它等于字符串需要'覆盖”修饰符

(这是斯卡拉如何与多重继承问题涉及 - 不管标识符多少次混合,它只存在一次)。因为Scala需要一点帮助在C建立类型界限

+1

换句话说,“不要忘了Scala的类型线性化”! – duckworthd

2

你第二个例子失败。我想也许它应该足够聪明,以便自己弄清楚,但是更熟悉类型理论的人将不得不解释为什么或者为什么不。 C的这个定义应该可以工作:

trait C extends A with B { 
    type O >: Z2 <: Z // restrict O's type so it's valid for both A and B 
} 

Scala处理抽象类型与处理抽象方法类似。同一名称(和签名)从多个特征中拉出的方法被一起覆盖。以经典反例为例,衍生自Ye Olde C++ Programming Language中给出的示例。

trait Cowboy { 
    /** Shoot something */ 
    def draw 
} 

trait Window { 
    /** Draw something */ 
    def draw 
} 

class CowboyWindow { 
    /** Probably best to draw something on the screen, then shoot it */ 
    def draw { 
    // ... 
    } 
} 

在它假设只有一个type O在你的代码的方式,它假定只有一个方法draw在此代码。在这种情况下,这个假设是有问题的,因为你最终可能会在脚下射击自己。

正如你在你的例子中发现的,通常这个假设是最好的(想想多个接口声明一个close()方法)。但是如果这个假设对于某些类来说是有问题的,就像CowboyWindow那样,你可以用继承来代替继承。

+0

处理抽象类型的上下界并不是我的问题的意图,但很高兴知道这一切!我没有意识到你可以同时放置一个类型的下限/上限 – duckworthd