如何设计不同种类的(几乎)相同的(在Scala中)

问题描述 投票:1回答:2

我在Scala中遇到以下问题...

我想读取wavefront文件(.obj),并将其转换为以后可以使用的文件。我要支持的wavefront文件是具有以下定义的文件:

  • TypeA:顶点和面
  • TypeB:顶点,纹理和面
  • TypeC:顶点,法线和面
  • TypeD:顶点,纹理,法线和面

我将阅读它们并使用以下字段为其创建一个Mesh(模型类,供以后使用):

  • TypeA:Array[Float]Array[Int]
  • TypeB:Array[Float]Array[Float]Array[Int]
  • TypeC:Array[Float]Array[Float]Array[Int]
  • TypeD:Array[Float]Array[Float]Array[Float]Array[Int]

我发现了两种方法:

1。方法:

每种类型都有自己的模型类

  • TypeA:case class TypeA(vertices: Array[Float], index: Array[Float])
  • TypeB:case class TypeB(vertices: Array[Float], textures: Array[Float], index: Array[Float])
  • TypeC:case class TypeC(vertices: Array[Float], normals: Array[Float], index: Array[Float])
  • TypeD: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])

使用这种方法,我只需要一个“构建”方法,但是这里的问题是,稍后我必须检查我要使用的字段是否确实存在(用于法线和纹理)

问题:

有人针对这种问题知道更好的方法/设计吗?

scala generics design-patterns .obj wavefront
2个回答
1
投票

通常,如果您知道要对这些类型执行的操作会有所帮助,那么一篇不错的博客文章是:https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction,其中作者认为错误的抽象比重复一些要糟得多。

采用方法1,也许为所有这些方法创建一个特征,然后您会看到是否可以将它们分组为类型,是否值得。


0
投票

方法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,但如果有其他可用的子类,它将创建适当的子类。然后,您可以创建MeshFaces,但是使用match来检测是否有附加信息可用。

© www.soinside.com 2019 - 2024. All rights reserved.