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

发布于 2024-12-08 17:05:47 字数 573 浏览 0 评论 0原文

假设我们有一个这样的类:

import java.net.URL
import xml._

class SearchData(xml: Node) {
  def this(url: URL) = this (XML.load(url))
}

并且我们想要在调用 this (XML.load(url)) 之前执行一些代码 - 比如说用 try 测试它。人们会期望编写这样的代码会起作用:

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

但事实并非如此,因为 Scala 要求您在重载构造函数中的第一个语句中调用 this() ,在本例中为 try 成为第一个语句。

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

Say we have a class like this:

import java.net.URL
import xml._

class SearchData(xml: Node) {
  def this(url: URL) = this (XML.load(url))
}

and we want to execute some code prior to calling this (XML.load(url)) - say test it with try. One would expect that writing something like this would work:

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

but it won't, because Scala requires that you make the call to this() the first statement in the overloaded constructor and in this case try becomes the first statement.

So what would be the solution to this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

那请放手 2024-12-15 17:05:47
def this(url: Url) = this(try {XML.load(url)} catch {case _ => <results/>})

更一般地,参数的计算必须在构造函数调用之前进行,因此您可以在那里执行此操作(scala 中的块是一个表达式,但编写一个例程,通常编写在伴生对象中,如果它会太长)。您不能做的是让此代码选择您调用的其他构造函数。但由于所有这些都必须路由到第一个,因此您不会损失太多。此外,您需要调用的另一个构造函数至少有一个参数。如果有多个构造函数,则第一个构造函数通常不应是没有参数的构造函数(请参阅 Scala 问题可选构造函数)

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

More generally, the evaluation of the arguments has to happen before the constructor call, so you do that there (a block in scala is an expression, but write a routine, typically written in the companion object, if it is going to be too long). What you cannot do is have this code choose which other constructor you call. But as all of them must route to the primary one, you do not lose much. Also, you need the other constructor you call to have at least one argument. If there are several constructors, the primary one should normally not be the one without an argument (see Scala problem optional constructor)

焚却相思 2024-12-15 17:05:47

伴生对象中的工厂方法:

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/" ) )

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

A factory method in companion object:

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/" ) )

Not only it simplifies design, but you can spare the new keyword.

回梦 2024-12-15 17:05:47

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

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

这里的技巧是 this 提供了执行匿名函数的结果,您可以在该函数的主体中执行任何操作。

但这仅在您具有单参数主构造函数时才有效 - 在其他情况下,您将不得不引入基于 Tuple 的解决方法:

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)
}

While didierd's solution solves the declared problem and is somewhat close to this one, it still doesn't solve the problem when you have to execute several statements prior to calling this. This one provides a general approach to all scenarios:

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

The trick here is that this is fed with result of executing an anonymous function in body of which you are allowed to do anything.

But this only works when you have a single-argument main constructor - in other scenarios you will have to introduce a Tuple-based workaround:

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)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文