Scala:拥有主要的所有实例

时间:2012-11-15 13:02:25

标签: scala

Scala中有一种方法可以在main中创建所有实例。

例如,我有以下类:作者,页面,书。 在主要内容中,我创建了这三个类的实例。 在Book的一个实例中我把作者和页面放了。

然后我想查看是否有不属于任何书籍的页面。

这个例子只是解释性的,你没有给它们太多的重视。

谢谢大家。 对不起英文翻译不好。

4 个答案:

答案 0 :(得分:3)

简短回答:不,没有完全自动化的方法来做到这一点。您需要迭代所有已分配的对象,这是垃圾收集器可以执行的操作,但程序本身不能。

以下是一种跟踪哪些子对象已附加到根对象的可能方式的草图。

定义允许我们区分子对象和根对象的基本特征:

trait Root

trait Sub {
  def register(r: Root)
  def deregister(r: Root)
  def isRegistered: Boolean
}

然后我们定义一个可以添加页面的根对象Book

class Book(val title: String) extends Root {
  private var pages: Set[Page] = Set()

  Books.books += this

  def add(p: Page) {
    pages += p
    p.register(this)
  }

  def remove(p: Page) {
    pages -= p
    p.deregister(this)
  }
}

在实例化时,每本书都将自己添加到全局存储库中:

object Books {
  var books: Set[Book] = Set()
}

同样适用于子对象Page

class Page(number: Int) extends Sub {
  private var owner: Option[Root] = None

  Pages.pages += this

  def register(r: Root) = owner match {
    case None =>
      owner = Some(r)
    case Some(o) =>
      sys.error("%s is already owned by %s, thus it cannot be owned by %s"
                .format(this, o, r))
  }

  def deregister(r: Root) = owner match {
    case Some(s) if r == s =>
      owner = None
    case Some(s) =>
      sys.error("%s is owned by %s, but not by %s"
                .format(this, s, r))
    case None =>
      sys.error("%s is not owned at all, thus also not by %s"
                .format(this, r))
  }

  def isRegistered = owner.nonEmpty
}

object Pages {
  var pages: Set[Page] = Set()

  def allRegistered = pages.forall(_.isRegistered)
}

一些用法示例:

val p1 = new Page(1)
val p2 = new Page(2)
val p3 = new Page(3)

val b1 = new Book("Fahrenheit 451")
val b2 = new Book("Brave New World")

b1.add(p1)
b1.add(p2)
b2.add(p3)

println(Pages.allRegistered) // true

val p4 = new Page(4)

println(Pages.allRegistered) // false

b2.add(p4)
b2.remove(p3)

println(Pages.allRegistered) // false

b2.add(p1) // Exception: already owned


注意:要牢记的设计决策,开放式问题:

  • 如果要销毁子对象,如何继续?将其从全局存储库中删除?

  • 子对象可以由多个根对象拥有吗?

  • 拥有多个非全局存储库会更好吗?这可能意味着我们需要工厂来创建和注册子对象。

  • 在并发设置中,我们必须同步对(全局)存储库的访问

  • 我们可以将(de)注册子对象的代码移动到单个特征中,然后在每个根对象中重用它吗?


注意II:如果我们有后退指针,我们只需要一个(全局)子对象存储库。但是,我不知道任何提供内置后投影仪的语言。

答案 1 :(得分:1)

不,你必须自己跟踪它们。不要认为任何语言真的这样做。当然,你可以用这样的方式写你的课程,但这是你的责任。

答案 2 :(得分:1)

你可以

// If you use the REPL, :paste both class and object together
class Page {
  Page.everything += this
  var booked: Option[Book] = None   // Or just set to null
}
object Page {
  val everything: collection.mutable.HashSet[Page] = collection.mutable.HashSet()
}

class Book {
  var pages: Vector[Page] = Vector()
  def addPage(p: Page) { p.booked = Some(this); pages = pages :+ p }
}

// Create all your books and pages and assign them all

Page.everything.filter(_.booked.isEmpty)   // This contains all unassigned pages

跟踪自己。 (这是假设单线程代码;在您的专业水平上,可能不值得担心如何并行执行此操作。)

或者,如果您想确保在main方法中发生所有事情,您可以执行类似

的操作
// File Page.scala
class Page(text: String)(implicit mhm: MustHaveMe) {
}

// File Main.scala
object Main {
  sealed trait MustHaveMe
  private final object YesYouHaveMe extends MustHaveMe
  def main(args: Array[String]) {
    implicit val okayHere = YesYouHaveMe
    new Page("Once upon a time")
  }
}

现在,访问限制将阻止除Main.scala以外的任何人创建新页面,并且只有main文件中的Main.scala方法才会隐藏创建{{1} }}。因此,您可以更轻松地避免在其他地方创建对象。

答案 3 :(得分:0)

我必须能够独立创建我的页面和书籍 我感兴趣的是跟踪创建的所有实例。 正如你所建议的那样,我想我也会部署我的课本:

class Book(var name: String, var pages: List[Page]){
AllBook.allbook += this
}

object AllBook {
var allbook: Set[Book] = Set()
}

以类似的方式也是类Page。 作为main方法中的最后一条指令,使用必须控制约束的方法调用“validation”。

这可能没问题? 有更好的解决方案吗?

注意:约束是独立的,尊重类的实现

对不起英文翻译不好