Использование абстрактных классов для построения кучи - PullRequest
0 голосов
/ 26 марта 2019

Я немного сбит с толку относительно фактической реализации кода из абстрактных классов и его значения.

Я написал код для Max Heap и хотел создать абстрактный класс на его основе, чтобы иметь общую схему для кучи, которая не является просто "Max".

Тело моего MaxHeap выглядит так:

public class MaxHeap {

    // A class for nodes, just has 3 fields, lchild, rchild, and value
    private HeapNode top;
    private List<HeapNode> heap;

    public MaxHeap() {
        this.top = null;
        this.heap = new ArrayList<>();
    }

    //I won't go into the guts of these methods, but will explain

    //Displays the heap like [1,2,3,4,5,...]
    public void display() {...}

    //Adds a new HeapNode to the end of heap, if empty sets to top
    public void add(int value) {...}

    //Deletes a HeapNode at index pos
    public void delete(int pos) {...}

    //Swaps 2 Nodes within the heap
    protected void swap(int pos, int otherPos) {...}

    //// These are the methods that actually differ depending on the
    //// type of heap (maxheap, minheap, etc) so I would assume they
    //// would be abstract methods if writing an abstract class?
    |
    |
    V

    //Called within add method, heapifys the heap after adding a new Node
    protected void addHeapify(int pos) {...}

    //Called within delete method, heapifys the heap after deleted Node
    protected void deleteHeapify(int pos) {...}

    //Called within deleteHeapify for "if (pos==0) {...}", delete max Node
    protected deleteExtremum() {...}
}

Мой вопрос отражает, как именно я бы реализовал это на более абстрактном уровне?Я хочу поднять кодирование на новый уровень, и мне нужно это понять.Буду ли я создавать абстрактный класс таким образом?

public abstract class Heap {

private HeapNode top;
private List<HeapNode> heap;

public Heap() {...}

// **************
// public methods
// **************

public void display() {...}
public void add(int value) {...}
public void delete(int pos) {...}

// ******************
// non-public methods
// ******************

protected void swap(int pos, int otherPos) {...}

// ****************
// abstract methods
// ****************

protected abstract void addHeapify(int pos);
protected abstract void deleteHeapify(int pos);
protected abstract void deleteExtremum();

}

Понимание правильного пути к «абстрактному-если» исходному классу очень поможет мне.

Правильно ли добавлять поля и конструктор в абстрактный класс, и, хотя add, delete, swap и display не меняются в разных кучах, должны ли эти методы быть абстрактными?

Мне также было интересно, стоит ли мне вместо этого использовать интерфейс, но он выглядит как более строгий абстрактный класс, и я не смогу определить add, delete, swap и display.

1 Ответ

1 голос
/ 26 марта 2019

Абстрактный класс - это обобщение нескольких конкретных классов.Он используется для обмена общими функциями и данными.Поскольку он абстрактный, его нельзя создать (использовать) без некоторой настройки.Если класс можно использовать как есть, он не является абстрактным.

Важным моментом, если вам нужен абстрактный класс для интерфейса, является то, что абстракция содержит данные.Вы можете иметь абстрактный класс с полями данных и только абстрактные методы.

Абстрактные методы следует использовать, когда ваша общая функциональность требует каких-либо данных или обработки для конкретного наследника.Например, если ваш метод add должен по какой-то причине вызывать addHeapify, но все равно, каким образом он реализован.

Если вам нужно, чтобы у всех потомков был какой-то метод, но он не используется в общей функциональности, разумно использовать интерфейс, так как интерфейс определяет, как должен вести себя класс, но не определяет, какие данные он содержит,Таким образом, вы можете иметь абстракцию двух классов, содержащих разные данные.В Java 8 вы можете реализовать default methods прямо в интерфейсе (раньше это было невозможно), поэтому вам нужен абстрактный класс, только если у вас есть общие данные для хранения в нем.

Имейте в виду, что ссылки на абстрактные классы или интерфейсы могут использоваться другими алгоритмами для вызова вашего, не зная, что является реализацией за ссылкой.Это в основном используется для того, чтобы сделать код переменным, так как вы можете заменить любую реализацию интерфейса или абстрактного класса без изменения клиентского кода.

...