Scala中有一种方法可以在main中创建所有实例。
例如,我有以下类:作者,页面,书。 在主要内容中,我创建了这三个类的实例。 在Book的一个实例中我把作者和页面放了。
然后我想查看是否有不属于任何书籍的页面。
这个例子只是解释性的,你没有给它们太多的重视。
谢谢大家。 对不起英文翻译不好。
答案 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”。
这可能没问题? 有更好的解决方案吗?
注意:约束是独立的,尊重类的实现
对不起英文翻译不好