仅有一个(两个)类型参数不同的构建器

时间:2017-11-05 20:24:56

标签: scala

object Thing {
  def apply[T](s: String, f: T => Option[Boolean]) = ThingBuilder(s, f)
  def apply[T](s: String, f: T => Option[Long]) = ThingBuilder(s, f)
}

sealed trait Thing[T, U] {
  def name: String
  def get(t: T): Option[U]
}

trait BooleanThing[T] extends Thing[T, Boolean]
trait LongThing[T] extends Thing[T, Long]

object ThingBuilder {
  def apply[T](s: String, f: T => Option[Boolean]) = new BooleanThing[T] {
    override final val name: String = s
    override final def get(t: T): Option[Boolean] = f(t)
   }

  def apply[T](s: String, f: T => Option[Long]) = new LongThing[T] {
    override final val name: String = s
    override final def get(t: T): Option[Long] = f(t)
  }
}

正如您所看到的,b / w BooleanThing[T]LongThing[T](类型U)之间只有一个区别。构建器应用方法基本上是复制/粘贴,并切换出类型U。有什么更好的方法可以做到这一点,以避免这种复制/粘贴的性质?

(顺便说一句,请不要建议我将一个特质改为一个类,我需要它们是这样的特征。)

1 个答案:

答案 0 :(得分:0)

我倾向于认为您可能需要根据您的要求将 function loadXMLDoc(filename) { if (window.ActiveXObject || "ActiveXObject" in window) { xhttp = new ActiveXObject("Msxml2.XMLHTTP"); } else { xhttp = new XMLHttpRequest(); } xhttp.open("GET", filename, false); xhttp.send(""); return xhttp.responseXML; } if (window.ActiveXObject || "ActiveXObject" in window) { ie(); } else { xml = loadXMLDoc("input.xml"); xsl = loadXMLDoc("mmlctop2_0.xsl"); if (document.implementation && document.implementation.createDocument) { xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(xsl); resultDocument = xsltProcessor.transformToDocument(xml, document); var serializer = new XMLSerializer(); var transformed = serializer.serializeToString(resultDocument.documentElement); alert(transformed); } } // https://msdn.microsoft.com/en-us/library/ms753809(v=vs.85).aspx function ie() { var xslt = new ActiveXObject("Msxml2.XSLTemplate.3.0"); var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.3.0"); var xslProc; xslDoc.async = false; xslDoc.load("mmlctop2_0.xsl"); if (xslDoc.parseError.errorCode != 0) { var myErr = xslDoc.parseError; alert("You have error " + myErr.reason); } else { xslt.stylesheet = xslDoc; var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0"); xmlDoc.async = false; xmlDoc.load("input.xml"); if (xmlDoc.parseError.errorCode != 0) { var myErr = xmlDoc.parseError; alert("You have error " + myErr.reason); } else { xslProc = xslt.createProcessor(); xslProc.input = xmlDoc; xslProc.addParameter("param1", "Hello"); xslProc.transform(); alert(xslProc.output); } } } 的{​​{1}}实例明确定义为Thing[T]BooleanThing[T]

否则,如果您需要操作的只是LongThing[T],隐藏第二个参数类型的具体类型,那么您可以在Thing[T]方法中添加另一个参数类型:

apply

以下使用Scala 2.12编译:

object Thing {
    def apply[S, T](s: String, f: T => Option[S]) = ThingBuilder(s, f)
}

...

object ThingBuilder {
   def apply[S, T](s: String, f: T => Option[S]) = new Thing[T, S] {
       override final val name: String = s
       override final def get(t: T): Option[S] = f(t)
   }
}

这样做的缺点是我们失去了特征val a1: Thing[Int, Boolean] = Thing("Hello, Boolean", (x: Int) => Some(true)) val a2: Thing[_, Boolean] = a1 val b1: Thing[String, String] = Thing("Hello, String", Some(_: String)) val b2: Thing[_, String] = b1 BooleanThing的特化。