Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:静态方法的继承vs.干式原理vs.封装_Scala_Oop - Fatal编程技术网

Scala:静态方法的继承vs.干式原理vs.封装

Scala:静态方法的继承vs.干式原理vs.封装,scala,oop,Scala,Oop,我试图在Scala中实现一个OOP范例。我将有一个抽象基类,包含50-100个子类。这些子类中的每一个子类都应该能够为测试目的生成一些随机实例。(事实上,我的真实生活场景比这要复杂得多,但我认为这足以回答这个问题。) 不管我怎么做,我对解决办法都不满意。我希望你们中的一些Scala专家能帮助我以Scala的方式思考这个问题 如果Scala中允许使用静态,我将执行以下操作: abstract class Base { protected val instanceValues: List[Som

我试图在Scala中实现一个OOP范例。我将有一个抽象基类,包含50-100个子类。这些子类中的每一个子类都应该能够为测试目的生成一些随机实例。(事实上,我的真实生活场景比这要复杂得多,但我认为这足以回答这个问题。)

不管我怎么做,我对解决办法都不满意。我希望你们中的一些Scala专家能帮助我以Scala的方式思考这个问题

如果Scala中允许使用静态,我将执行以下操作:

abstract class Base {
  protected val instanceValues: List[SomeType] // i.e. row-number, full-URL etc.
  def toString():String = "Base[" + classValues.toString() + "]: " + instanceValues.toString()
  protected static def classValues: SomeOtherType // i.e. table-name, domain-name etc.
  static def genData(): List[Base] = /* some default implementation using only classValues */
}

class A(override val instanceValues: List[SomeType]) extends Base {
  protected static def classValues = new SomeType(/* A-specific */)
}

...

class Z(override val instanceValues: List[SomeType]) extends Base {
  protected static def classValues = new SomeType(/* Z-specific */)
}

class SpecialCase(override val instanceValues: List[SomeType]) extends Base {
  protected protected def classValues = new SomeType(/* SpecialCase-specific */)
  override static def genData(): List[Base] = /* something specific to this subclass not easily expressed elegantly using classValues */
}
但是,由于Scala中不允许使用静态,因此它从来都不是一个真正的解决方案

阅读类似这样的内容(注意:这个问题不是那个问题的重复-我认为这涉及到使用伴生对象解决方案的不雅性),相反,我需要创建28个相同的伴生对象来容纳classValues和genData方法:

abstract class Base {
  protected val instanceValues: List[SomeType]
}

class A(override val instanceValues: List[SomeType]) extends Base {
  def toString():String = "Base[" + A.classValues.toString() + "]: " + instanceValues.toString()
}
object A {
  private val classValues: SomeOtherType
  static def genData(): List[Base] = /* some default implementation using only classValues */
}

...

class Z(override val instanceValues: List[SomeType]) extends Base {
  def toString():String = "Base[" + Z.classValues.toString() + "]: " + instanceValues.toString()
}
object Z {
  private val classValues: SomeOtherType
  static def genData(): List[Base] = /* some default implementation using only classValues */
}

class SpecialCase(override val instanceValues: List[SomeType]) extends Base {
  def toString():String = "Base[" + SpecialCase.classValues.toString() + "]: " + instanceValues.toString()
}
object SpecialCase {
  private val classValues: SomeOtherType
  static def genData(): List[Base] = /* something specific for SpecialCase */
}
除了有相当多的膨胀之外,这个解决方案似乎违反了DRY原则,它迫使我以几乎相同的方式重新实现SharedToString方法。最后,这意味着任何扩展Base的人都应该记住为新类添加一个伴随对象

另一种解决方案是有一个“测试数据”-工厂:


但这需要我打开对instanceValues和classValues字段的读取权限,这是不可取的。

对于后代来说:我最终改变了我的体系结构,使其包含trait和object,并使用“覆盖”的内部类来创建实例。这并不是很漂亮,但至少我避免了问题中列出的缺陷。

这可以通过使用代数数据类型轻松解决。谷歌这个词。当我有更多的时间,我会发布一个解决方案,如果没有其他人在这期间。可能重复的我不认为这个问题是一个重复的问题。其中一个涉及如何在Scala中进行“静态”。在我看来,这涉及到在我的用例中使用伴生对象解决方案的不雅性。@I.K.我已经阅读了代数数据类型,虽然它们很有趣,但我看不出它们在这里有什么帮助,所以我当然希望你能在某个时候有更多的时间发表文章。
abstract class Base {
  val instanceValues: List[SomeType]
  def classValues: SomeOtherType
  def toString():String = "Base[" + classValues.toString() + "]: " + instanceValues.toString()
}

object TestDataGenerator {
  def genData(clss:String): List[Base] = clss match {
    case "SpecialCase" => /* something specific to SpecialCase */
    case other => /* some default implementation using reflection for creation and some kind of manipulation of the SomeType and SomeOtherType objects after creation */
  }
}

class A(override val instanceValues: List[SomeType]) extends Base {
  def classValues = new SomeType(/* A-specific */)
}

...

class Z(override val instanceValues: List[SomeType]) extends Base {
  def classValues = new SomeType(/* Z-specific */)
}

class SpecialCase(override val instanceValues: List[SomeType]) extends Base {
  def classValues = new SomeType(/* SpecialCase-specific */)
}