我开始学习Scala编程和OOP编程。我不理解抽象类的概念。我读过这个例子:
考虑为带有两个运算(包括和)的整数集编写类的任务。(s incl x)应该返回一个新集合,其中包含元素x和集合s的所有元素。(s包含x)如果set s包含元素x,则应返回true,否则应返回false。这样的集合的接口由下式给出:
abstract class IntSet {
def incl(x: Int): IntSet
def contains(x: Int): Boolean
}
假设我们计划将集合实现为二叉树。有两种可能的树木形式。空集的树,以及由整数和两个子树组成的树。这是它们的实现。
class EmptySet extends IntSet {
def contains(x: Int): Boolean = false
def incl(x: Int): IntSet = new NonEmptySet(x, new EmptySet, new EmptySet)
}
class NonEmptySet(elem: Int, left: IntSet, right: IntSet) extends IntSet {
def contains(x: Int): Boolean =
if (x < elem) left contains x
else if (x > elem) right contains x else true
def incl(x: Int): IntSet =
if (x < elem) new NonEmptySet(elem, left incl x, right)
else if (x > elem) new NonEmptySet(elem, left, right incl x)
else this
}
EmptySet和NonEmptySet都扩展了IntSet类。这意味着类型EmptySet和NonEmptySet符合类型IntSet –在需要IntSet类型的值的任何地方都可以使用类型EmptySet或NonEmptySet的值。
我不清楚为什么引入匿名类很有用,因为在扩展匿名类的两个类中,又包含了incl和contains的定义。
谢谢!
使用InClass
(这是一个抽象类,而不是一个匿名类)的主要优点是它定义了一种元素类型,其实例必须始终实现incl
,contains
因此允许您在管理设置对象的情况下抽象实现细节。
一个很好的例子是,您可以拥有一组集合Empty
并NomEmpty
一起使用抽象类给出的协定来模糊地使用它们:
val l = List[IntSet](new EmptySet, new NomEmptySet(1, new EmptySet, new EmptySet)
val setsContainingThree = l.filter(_.contains(3))
您的代码利用了这一点,请注意,我写了,new NomEmptySet(1, new EmptySet, new EmptySet)
但也可能是:
new NomEmptySet(1, new EmptySet, new NomEmptySet(2, new EmptySet, new EmptySet))
你的NonEmptySet
构造函数需要InSet
因此您的实际参数可以通过任何类型的为子类InSet
,即:EmptySet
或NonEmptySet
。
这不是Scala或Java功能,而是OOP的基本原理。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句