亲爱的Scala开发人员,
我有两个Scala项目,分别为core
和infra
。 core
项目包含特征定义,而infra
包含这些特征的具体实现。因此,infra
取决于core
。
在core
项目中,我具有使用蛋糕模式的特征。
trait GetSectionsOfTypeComp {
def sectionsOfType[SectionType <: SoftwareSection](implicit evidence: GetSectionsOfType[SectionType]): GetSectionsOfType[SectionType]
trait GetSectionsOfType[SectionType <: SoftwareSection] {
def getAll(dataStream: InputStream): Seq[SectionType]
}
}
其中SoftwareSection
是一个有一个孩子的特征:
sealed trait SoftwareSection {
def name: String
def rawAddress: SoftwareAddress
def rawSize: Long
}
case class CodeSoftwareSection(name: String, rawAddress: SoftwareAddress, rawSize: Long) extends SoftwareSection
在infra
项目中,我想根据方法GetSectionsOfType.sectionsOfType
的类型参数来分离逻辑。因此,我使用类型类:
trait PeParserGetSectionsOfCodeComp extends GetSectionsOfTypeComp {
implicit val foo: GetSectionsOfType[CodeSoftwareSection] = GetSectionOfCode
override def sectionsOfType[SectionType <: SoftwareSection](implicit evidence: GetSectionsOfType[SectionType]): GetSectionsOfType[SectionType] = evidence
implicit object GetSectionOfCode extends GetSectionsOfType[CodeSoftwareSection] {
override def getAll(dataStream: InputStream): Seq[CodeSoftwareSection] = Seq(CodeSoftwareSection("code", SoftwareAddress(0), 0))
}
}
trait PeParserGetSectionsOfDataComp extends GetSectionsOfTypeComp {
implicit val bar: GetSectionsOfType[DataSoftwareSection] = GetSectionOfData
override def sectionsOfType[SectionType <: SoftwareSection](implicit evidence: GetSectionsOfType[SectionType]): GetSectionsOfType[SectionType] = evidence
implicit object GetSectionOfData extends GetSectionsOfType[DataSoftwareSection] {
override def getAll(dataStream: InputStream): Seq[DataSoftwareSection] = Seq(DataSoftwareSection("data", SoftwareAddress(0), 0))
}
}
位于项目core
中的我的业务逻辑需要调用sectionsOfType
实例的方法GetSectionsOfType
,该方法将使用蛋糕模式轻轻地注入。
由于项目core
对infra
项目没有(也不应该具有!)依赖性,因此调用方法sectionsOfType[CodeSoftwareSection].getAll(openStream)
会使编译器感到生气,因为它不能找到隐式参数的任何隐式值,这很正常!
现在,我不能只导入GetSectionsOfType
的所有实现,因为它将在我的项目core
中公开该实现。为了解决这种情况,我阅读了Scala文档中的文章WHERE DOES SCALA LOOK FOR IMPLICITS?,希望找到另一种方式来解决我的隐式问题,而又不会依赖于项目{{1} }。
不幸的是,我找不到任何方法来解决我的隐式问题,因为项目core
无法链接项目infra
,隐式参数必须在编译时解决。
是否有任何建议或替代方法来保持代码的清洁?
编辑3 :使用蛋糕模式重构代码。
编辑4 :在下面的项目core
中向组件添加调用示例。
infra
答案 0 :(得分:0)
关于您当前代码的一些观察结果:
在您的GetSectionsOfTypeComp
中,您可以写作
trait GetSectionsOfTypeComp {
def sectionsOfType[SectionType <: SoftwareSection](implicit evidence: GetSectionsOfType[SectionType]): GetSectionsOfType[SectionType] = evidence
}
如果您要做的就是在每个(或至少许多)实施中返回evidende。
此外,您不必为隐式对象创建implicit val
。
这绝对不是必须的,但是您可以避免为GetSectionsOfTypeComp
创建子类型,同时将类型类代码分开。您最终会遇到这种情况:
import java.io.InputStream
// type class code
trait GetSectionsOfType[SectionType <: SoftwareSection] {
def getAll(dataStream: InputStream): Seq[SectionType]
}
object GetSectionsOfType {
implicit object GetSectionOfCode extends GetSectionsOfType[CodeSoftwareSection] {
override def getAll(dataStream: InputStream): Seq[CodeSoftwareSection] = Seq(CodeSoftwareSection("code", SoftwareAddress(0), 0))
}
implicit object GetSectionOfData extends GetSectionsOfType[DataSoftwareSection] {
override def getAll(dataStream: InputStream): Seq[DataSoftwareSection] = Seq(DataSoftwareSection("data", SoftwareAddress(0), 0))
}
}
// component
trait GetSectionsOfTypeComp {
def sectionsOfType[SectionType <: SoftwareSection](implicit evidence: GetSectionsOfType[SectionType]): GetSectionsOfType[SectionType] = evidence
}
对于实际问题,我不知道您的所有代码,但您将核心项目定义为特征定义的地方。对于核心项目了解实现是个好主意吗?您是否不应该考虑将呼叫放在其他地方(例如新模块)?要确定有关呼叫站点的更多知识,就需要。
希望这会有所帮助。