我在Scala中遇到以下问题...
我想读取wavefront文件(.obj),并将其转换为以后可以使用的文件。我要支持的wavefront文件是具有以下定义的文件:
我将阅读它们并使用以下字段为其创建一个Mesh(模型类,供以后使用):
Array[Float]
,Array[Int]
Array[Float]
,Array[Float]
,Array[Int]
Array[Float]
,Array[Float]
,Array[Int]
Array[Float]
,Array[Float]
,Array[Float]
,Array[Int]
我发现了两种方法:
1。方法:
每种类型都有自己的模型类
case class TypeA(vertices: Array[Float], index: Array[Float])
case class TypeB(vertices: Array[Float], textures: Array[Float], index: Array[Float])
case class TypeC(vertices: Array[Float], normals: Array[Float], index: Array[Float])
case class TypeD(vertices: Array[Float], textures: Array[Float], normals: Array[Float], index: Array[Float])
使用这种方法,我不必检查是否所有字段都存在。我可以直接使用它们。缺点是:我需要为每种类型创建“构建”方法(类似:createTypeAFromFile(filename: String)
)
2。方法我创建类似uber-model的东西:
case class Mesh(vertices: Array[Float], textures: Option[Array[Float]], normals: Option[Array[Float]], index: Array[Float])
使用这种方法,我只需要一个“构建”方法,但是这里的问题是,稍后我必须检查我要使用的字段是否确实存在(用于法线和纹理)
问题:
有人针对这种问题知道更好的方法/设计吗?
通常,如果您知道要对这些类型执行的操作会有所帮助,那么一篇不错的博客文章是:https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction,其中作者认为错误的抽象比重复一些要糟得多。
采用方法1,也许为所有这些方法创建一个特征,然后您会看到是否可以将它们分组为类型,是否值得。
方法3是创建一个类层次结构来表示不同的选项。
trait Faces {
def vertices: Array[Float]
def faces: Array[Float]
}
trait Textures {
Faces =>
def textures: Array[Float]
}
trait Normals {
Faces =>
def normals: Array[Float]
}
class A(
val vertices: Array[Float],
val faces: Array[Float]
) extends Faces
class B(
val vertices: Array[Float],
val textures: Array[Float],
val faces: Array[Float]
) extends Faces with Textures
class C(
val vertices: Array[Float],
val normals: Array[Float],
val faces: Array[Float]
) extends Faces with Normals
class D(
val vertices: Array[Float],
val textures: Array[Float],
val normals: Array[Float],
val faces: Array[Float]
) extends Faces with Textures with Normals
解析器可以返回Faces
,但如果有其他可用的子类,它将创建适当的子类。然后,您可以创建Mesh
的Faces
,但是使用match
来检测是否有附加信息可用。