我在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。方法 我创建了一个超级模型:
case class Mesh(vertices: Array[Float], textures: Option[Array[Float]], normals: Option[Array[Float]], index: Array[Float])
使用这种方法,我只需要一个“构建”方法,但是这里的问题是,稍后我必须检查我要使用的字段是否真的存在(用于法线和纹理)
问题:
有人针对这种问题知道更好的方法/设计吗?
答案 0 :(得分:2)
如果您知道要对这些类型执行的操作通常会有所帮助,一个不错的博客文章是:https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction,其中作者认为错误的抽象比重复一些要糟得多。
采用方法1,也许为所有这些方法创建一个特征,您将看到是否可以将它们分组为类型,是否值得。
答案 1 :(得分:2)
[感谢@simpadjo更新]
方法3是创建一个特征层次结构来表示不同的选项:
trait Faces {
def vertices: Array[Float]
def faces: Array[Float]
}
trait Textures extends Faces {
def textures: Array[Float]
}
trait Normals extends Faces {
def normals: Array[Float]
}
trait Obj3D extends Textures with Normals
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 Textures
class C(
val vertices: Array[Float],
val normals: Array[Float],
val faces: Array[Float]
) extends Normals
class D(
val vertices: Array[Float],
val textures: Array[Float],
val normals: Array[Float],
val faces: Array[Float]
) extends Obj3D
解析器可以返回Faces
,但如果有其他字段可用,它将创建适当的子类。然后,您可以创建Mesh
中的Faces
,但是使用match
来检测是否有附加信息可用。