Реализация абстрактных классов в Scala

1

Я начинаю изучать программирование Scala и программирование ООП. Я не понимаю понятие абстрактного класса. Я прочитал этот пример:

Рассмотрим задачу написания класса для множеств целых чисел с двумя операциями, включая и содержит. (s с x) должен возвращать новый набор, содержащий элемент x вместе со всеми элементами множества s. (s содержит x) должен возвращать true, если множество s содержит элемент x и в противном случае должно возвращать 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 - значение типа EmptySet или NonEmptySet может использоваться везде, где требуется значение типа IntSet.

Мне непонятно, почему полезно вводить анонимный класс, поскольку в двух классах, которые расширяют анонимный, снова появляется определение вставки и содержит.

Благодарю!

  • 0
    Я не могу понять, как рекурсия работает в методе incl. Пожалуйста помоги
Теги:
oop
abstract-class

2 ответа

0
Лучший ответ

Основным преимуществом использования 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, а основной принцип ООП.

0

Класс не анонимный, он абстрактный. Какой -in простой words- означает, что вы не можете его создать. Однако вы можете использовать его, например, в сигнатуре метода... вы никогда не узнаете, какая реализация передана вашему методу, но оба предлагают один и тот же интерфейс для взаимодействия с ними (поскольку оба являются IntSet s).

Если это помогает, вы можете думать об абстрактном классе как о интерфейсе с реализациями метода или как о простой форме признака.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню