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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.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 在调用this()之前在重载构造函数中执行代码_Scala_Constructor_Overloading - Fatal编程技术网

Scala 在调用this()之前在重载构造函数中执行代码

Scala 在调用this()之前在重载构造函数中执行代码,scala,constructor,overloading,Scala,Constructor,Overloading,假设我们有这样一节课: import java.net.URL import xml._ class SearchData(xml: Node) { def this(url: URL) = this (XML.load(url)) } 我们希望在调用this(XML.load(url))之前执行一些代码-说用测试。有人会认为写这样的东西是可行的: class SearchData(xml: Node) { def this(url: URL) { try {

假设我们有这样一节课:

import java.net.URL
import xml._

class SearchData(xml: Node) {
  def this(url: URL) = this (XML.load(url))
}
我们希望在调用
this(XML.load(url))
之前执行一些代码-说用
测试
。有人会认为写这样的东西是可行的:

class SearchData(xml: Node) {
  def this(url: URL) {
    try {
        this (XML.load(url))
    } catch {
      case _ => this(<results/>)
    }
  }
}
类搜索数据(xml:Node){
定义此(url:url){
试一试{
这是(XML.load(url))
}抓住{
case=>this()
}
}
}
但它不会,因为Scala要求调用重载构造函数中的第一条语句
this()
,在这种情况下,
try
成为第一条语句

那么这个问题的解决方案是什么呢?

def this(url:url)=this(try{XML.load(url)}catch{case})
def this(url: Url) = this(try {XML.load(url)} catch {case _ => <results/>})

更一般地说,参数的求值必须在构造函数调用之前进行,因此您可以在那里进行(scala中的一个块是一个表达式,但是如果它太长,请编写一个例程,通常在伴随对象中编写)。您不能让此代码选择您调用的其他构造函数。但是,由于所有这些都必须经过初级通道,因此您不会损失太多。此外,您还需要调用另一个构造函数来至少有一个参数。如果有多个构造函数,则主构造函数通常不应是没有参数的构造函数(请参见同伴对象中的工厂方法):

object SearchData {
  def apply(xml: Node) = new SearchData(xml) //Added to provide uniform factories
  def apply(url: URL) = {
    try {
      new SearchData(XML.load(url))
    } catch {
      case _ => new SearchData(<results/>)
    }
  }
}

//Example
val sd = SearchData( new URL( "http://example.com/" ) )
对象搜索数据{
def apply(xml:Node)=新的SearchData(xml)//添加以提供统一的工厂
def应用(url:url)={
试一试{
新的SearchData(XML.load(url))
}抓住{
case=>newsearchdata()
}
}
}
//范例
val sd=搜索数据(新URL(“http://example.com/" ) )

它不仅简化了设计,还可以省去
new
关键字。

虽然didierd的解决方案解决了已声明的问题,并且有点接近这个问题,但在调用
this
之前必须执行多个语句时,它仍然无法解决问题。该方法提供了所有场景的通用方法:

class SearchData(xml: Node) {
  def this(url: URL) = this {
    println(url)
    try {
      XML.load(url)
    } catch {
      case _ => <results/>
    }
  }
}

我看不出它是如何简化设计的。它还迫使您要么根据场景通过构造包含和不包含
new
关键字的对象来引入不一致性,要么违反DRY规则,为类中的所有构造函数(包括主构造函数)创建伴随别名,这样您就可以始终构造不包含
new
的对象。然而,您仍然必须始终使用
new
构建库类。实际上,这种模式在scala库中非常常见,并自动为案例类实现。所以矛盾已经存在了。另外,构造函数在大多数情况下都会向客户机透露太多的缺点,即结果的确切类型和它是新创建的事实。工厂不值得一直这样做,但它们通常很方便,虽然它确实困扰着我,但我不会就此止步。我很怀念Delphi中的构造函数和静态函数,它们的调用方式与客户端相同。我完全同意你的看法。实际上,他们解决这个问题的方法是完全去掉
new
关键字。对我来说很奇怪Scala的人没有发现问题。它简化了设计,因为构建对象只有一种方法:构造函数。所以先打电话没问题。。。这种工厂只是语法上的糖厂,可以让用户省去额外的强制性步骤。顺便说一句,我更新了代码以解决不一致性。这是一个很好的解决已声明问题的方法,但它不是通用的。也许是我的错,我宣布了一个误导性的琐碎问题。不管怎样,看看哪一个在某种程度上改进了你的解决方案。我想我的评论涵盖了你第一个使用println的案例。但是你在第二个案例中提出了一个很好的观点。
class SearchData(xml: Node, valid: Boolean) {
  def this(url: URL) = this {
    println(url)
    try {
      (XML.load(url), true)
    } catch {
      case _ => (<results/>, false)
    }
  }
  def this(t: (Node, Boolean)) = this(t._1, t._2)
}