【问题标题】:Scala: Is there a function that returns a child object's parent?Scala:是否有返回子对象父对象的函数?
【发布时间】:2023-03-31 05:29:01
【问题描述】:

假设我们有两个对象,A 和 B,它们具有父子关系。比如:

    A.child = B

在 Scala 中是否有一个函数或某种方法可以像这样工作:

    B.getParent() //returns A

【问题讨论】:

  • 是的,但是你需要写一个。 TBH 这个问题根本没有多大意义。能不能详细点?

标签: scala


【解决方案1】:

Scala 没有内置的能力来管理这种关系。

但是,将父成员添加到B 的构造函数并按如下方式填充它是微不足道的:

class A {
  val child = new B(this)
  // ...
}

class B(val parent: A) {
  // ...
}

// Some possible actions:
val a = new A
val b = a.child
a == b.parent // Should be true

在这种特殊情况下,A 还负责构造B,这使得AB 都是不可变的。

这个主题有很多变化。

一种更通用的方法是使用外部映射来跟踪关系,它允许AB 的实例不那么紧密耦合。以下是如何以功能方式完成此操作的示例:

class A {
  // ...
}

class B {
  // ...
}

// Constructor is private to require construction through companion's factory method.
class Relationships private(private val parentToChild: Map[A, B], private val childToParent: Map[B, A]) {

  // Return new relationship that adds relationship between child and parent instance.
  //
  // This particular approach assumes a one-to-one mapping (one child per parent).
  // One-to-many (multiple children per parent) are possible by mapping the parent to a
  // collection of children.
  def relate(parent: A, child: B): Relationships = {

    // Verify that neither parent nor child currently have relationships.
    require(!parentToChild.contains(parent) && !childToParent.contains(child))

    // Add the relationship, return new relationships instance.
    val newParentToChild = parentToChild + (parent -> child)
    val newChildToParent = childToParent + (child -> parent)
    new Relationships(newParentToChild, newChildToParent)
  }

  // Lookup child of particular parent. Return None if no child found, Some(child) otherwise.
  def childOf(parent: A): Option[B] = parentToChild.get(parent)

  // Lookup parent of particular child. Return None if no parent found, Some(parent) otherwise.
  def parentOf(child: B): Option[A] = childToParent.get(child)
}

// Companion.
object Relationships {

  // Create initial relationship instance with no relationships.
  def apply() = new Relationships(Map.empty[A, B], Map.empty[B, A])
}

// Sample use:
val a = new A
val b = new B
val tracker = Relationships().relate(a, b)
tracker.childOf(a) // Should return Some(b).
tracker.parentOf(b) // Should return Some(a).

【讨论】:

    【解决方案2】:

    一种解决方案是使用名称参数和lazy val,如下所示...

    class TreeNode[E](l: => Option[TreeNode[E]], value: E, r: => Option[TreeNode[E]], p: => Option[TreeNode[E]]) {
    
      lazy val left: Option[TreeNode[E]] = l
    
      lazy val right: Option[TreeNode[E]] = r
    
      lazy val parent: Option[TreeNode[E]] = p
    
    }
    
    // must explicitly define the types for left and right!
    val left: TreeNode[Int] = new TreeNode(None, 6, None, Some(root))
    val right: TreeNode[Int] = new TreeNode(None, 15, None, Some(root))
    val root = new TreeNode(Some(left), 10, Some(right), None)
    

    请注意,case classes 中不允许使用按名称参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多