我习惯于使用函数式编程(主要是 Haskell),我从 OO(scala)开始。
我在翻译我的代码时遇到了麻烦。例如,这是我对 B-tree 的 Haskell 定义:
data BTree a =
Leaf
|Node2 (BTree a) a (BTree a)
|Node3 (BTree a) a (BTree a) a (BTree a)
deriving (Eq,Read,Show)
这很简单。我的树是空的,或者它有一个值并且是两棵树的父亲,或者它是三棵子树的父亲。
OO上有什么?我没有任何线索。我只是无法弄清楚我该如何以理智的方式做到这一点。
最佳答案
这里有一些很好的答案,但我认为他们都错过了展示你所缺少的观点的机会。所以,你已经证明了这一点:
data BTree a =
Leaf
|Node2 (BTree a) a (BTree a)
|Node3 (BTree a) a (BTree a) a (BTree a)
deriving (Eq,Read,Show)
并询问您如何以面向对象的方式实现这一点。所以,这里是:
最重要的事情
trait Tree[A] {
// not required because it is inherited from AnyRef
// def equals(other: Any): Boolean
// not required because it is inherited from AnyRef
// def toString: String
// does not belong in the object
// def fromString(input: String): Tree[A]
// Stuff that is missing but is needed
def isEmpty: Boolean
def value: Option[A]
def subtrees: Seq[Tree[A]]
def iterator: Iterator[A]
def depthFirstIterator: Iterator[A]
def breadthFirstIterator: Iterator[A]
}
所以,问题是这样的:当你谈到面向对象时,你有一个 BTree、一个手指树或任何其他不相关的树结构。事实上,它应该被隐藏起来。相关的是你可以用它做什么。
您在这样做时遇到了麻烦,因为您正在从不应该的方向准确地解决问题。
不那么重要的事情
sealed abstract class BTree[A] extends Tree[A]
object BTree {
def apply[A](input: String): BTree[A] = { /* factory */ null.asInstanceOf[BTree[A]] }
private case object Leaf extends BTree[Nothing] {
// method implementation
}
private case class Node2[A](value: A, private one: BTree[A], private two: BTree[A]) extends BTree[A] {
// method implementation
}
private case class Node3[A](value: A, private one: BTree[A], private two: BTree[A], private three: BTree[A]) extends BTree[A] {
// method implementation
}
}
现在在这里你实际上提供了一个实现,但是 BTree 的细节是完全隐藏的。您只能使用
Tree
的方法。已定义。这是理想的面向对象架构:客户端依赖于接口(interface),数据结构是隐藏的。
关于scala - 从函数式迁移到 OO 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4348788/