多次混合相同特性的规则

时间:2011-08-13 16:03:57

标签: scala mixins

我试图编写一些抽象代码,使其逐步变得更加复杂。它在其中一个步骤中打破了。

第1步,正确

trait Base
trait C1 extends Base

trait Abst extends Base
trait Conc extends Abst with C1

第二步,正确

object BaseHolder {
  trait Data
}

object C1Holder {
  trait Data extends BaseHolder.Data
}

trait Abst extends BaseHolder.Data
trait Conc extends Abst with C1Holder.Data

第3步,错误错误

trait BaseHolder {
  trait Data
}
object BaseHolder extends BaseHolder

trait C1Holder extends BaseHolder {
  trait Data extends super.Data
}
object C1Holder extends C1Holder

trait Abst extends BaseHolder.Data
trait Conc extends Abst with C1Holder.Data

我有错误:     非法继承; trait Con继承了特征数据的不同类型实例

这个错误意味着什么,有没有办法绕过它?

2 个答案:

答案 0 :(得分:6)

完整的错误消息是

[error]  trait Conc inherits different type instances of trait Data:
[error] C1Holder.Data and BaseHolder.Data
[error] trait Conc extends Abst with C1Holder.Data
[error]       ^
[error] one error found

它说(object BaseHolder).Data(object C1Holder).Data不一致,因为虽然后者符合(trait BaseHolder)#Data,但这不像单身实例trait Data中的object BaseHolder那么具体}。

修改的。请注意,类型和值存在于不同的名称空间中,因此单独使用名称BaseHolder是不明确的,它可以引用对象的特征。但是,当提到一个类型时,“。”或“#”符号消除歧义:

  1. T#Data始终表示类型 Data中的T类型成员。例如,BaseHolder#Data将引用特征BaseHolder

  2. x.Data始终表示对象 Data中的x类型成员。例如,BaseHolder.Data将引用单身对象BaseHolder

  3. 请注意,x的两个ytrait BaseHolder个实例将具有不同的类型x.Datay.Data;这是路径依赖类型的工作方式。另请注意,object BaseHolder extends BaseHolder只是trait BaseHolder的一个特定实例。

    要让您的代码进行编译,请确保(trait C1Holder)#Data实际符合(object BaseHolder).Data

    trait BaseHolder {
      trait Data
    }
    object BaseHolder extends BaseHolder
    
    trait C1Holder extends BaseHolder {
      trait Data extends BaseHolder.Data // Here BaseHolder refers to singleton object
    }
    object C1Holder extends C1Holder
    
    trait Abst extends BaseHolder.Data
    trait Conc extends Abst with C1Holder.Data
    

    在这个例子中,特征没有做太多,所以你可能只想使用

    object BaseHolder {
      trait Data
    }
    
    object C1Holder {
      trait Data extends BaseHolder.Data
    }
    
    trait Abst extends BaseHolder.Data
    trait Conc extends Abst with C1Holder.Data
    

答案 1 :(得分:2)

您将外部特征视为内在特征的简单容器,几乎就像处理包装一样。然而,内部类和特征与其父类之间的关系更为复杂。

内部类和特征始终与父类的实例相关联。没有父实例就无法创建内部类。实际上,内部类有一个隐藏引用,指向父类的实例。

在您的情况下,特征数据与对象BaseHolder相关联。然后特征Abst扩展了BaseHolder.Data,因此它也与对象BaseHolder相关联。这意味着Abst将引用BaseHolder对象作为其父对象。

另一方面,C1Holder.Data引用C1Holder作为其父级。因此,当您定义Conc时,它必须引用BaseHolder和C1Holder作为父级。但内在特征只能有一个父母。因此错误。

相关问题