Наследование Java против композиции (реализация стека)

StackOverflow https://stackoverflow.com/questions/1419115

Вопрос

Я пытаюсь реализовать стек в Java (используя интерфейс списка: Список интерфейсов).

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

Для наследования на данный момент у меня есть:

 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;

 public class StackInheritance implements List {
      //implement list methods
 }

Для композиции у меня есть:

 import java.util.List;

 public abstract class StackComposition implements List {
     // implement some standard methods
 }

 public class StackViaList extends StackComposition {
     // implement methods that have not been implemented in the abstract
     // class
 }

Я в замешательстве, куда идти дальше.Я никогда раньше не использовал интерфейс, так должен ли я использовать методы List для «имитации» стека, например, используя Array или ArrayList?

Кроме того, что касается композиции, я не понимаю, какие методы должны идти в StackComposition, а какие — в StackViaList.Я немного растерялся из-за не полного понимания интерфейсов, а также наследования и композиции.Я пока не могу просто "понять"...

Любая помощь будет оценена по достоинству, спасибо!

Это было полезно?

Решение

Для компоновки класс стека должен иметь список, а не реализовывать или расширять класс на основе списка. Наследование является «А». отношения, в то время как композиция является "HAS A" отношения.

Например:

public class StackWithComposition
{
    // StackWithComposition HAS A List (rather than IS A List)
    private List myList = new ArrayList();

    public void push(object item)
    {
        // add item to myList, etc.
    }

    public object pop()
    {
        // return item at top (or end) of myList
    }

    // etc.
}

Обратите внимание, что вы, вероятно, захотите сделать этот класс универсальным, а не иметь дело с необработанными объектами, но это было бы идеей.

В этом случае решение на основе композиции, вероятно, предпочтительнее решения на основе наследования. Когда вы наследуете от класса / интерфейса, вы должны спросить себя, является ли стек списком? Большинство стеков не должны предоставлять пользователю доступ ко всем необработанным методам List, поэтому лучше скрыть лицо, которое вы используете List в качестве внутренней структуры данных. Использование составного списка позволяет полностью скрыть тот факт, что вы используете список в качестве внутренней структуры.

Другие советы

Я не думаю, что это настоящий вопрос.Это вопрос типа «можешь ли ты сделать за меня домашнее задание?».

Более содержательными вопросами были бы:

  • В чем разница между наследованием и композицией?
  • Каковы преимущества/недостатки реализации стека с каждым из них?
  • Что такое стек?

Энди дал хорошие ответы на все три вопроса.

К сожалению, похоже, что учитель оригинального плаката сам не очень хорошо понимает концепции, поскольку задание бессмысленно.Класс, реализующий java.util.List, не является стеком, или, скорее, его небезопасно использовать в качестве стека, поскольку он требует, чтобы небезопасные для стека операции были общедоступными.Стек — гораздо более ограничивающий интерфейс, чем список.

Неудивительно, что оригинальный постер запутан.

У вас перевернутые понятия.

Наследование, как говорится, это когда вы «берёте» у существующего объекта функциональность.Это известно как отношение ЕСТЬ-А.Например, грузовик ЭТО Транспортное средство.

В вашем первом примере это не наследование, потому что вы ничего не берете из списка.В вашем образце вы «реализуете» этот список, а не «расширяете» его.

Состав это когда вы создаете объект, используя других (вы объединяете объекты).Это известно как отношение HAS-A.Например, грузовик ИМЕЕТ колесо (но это не колесо).В вашем образце вы «расширяете» (наследуете) от другого объекта.

Окончательно интерфейс в ООП — это «контракт», который объект обязан выполнить.На какие функции или сообщения будет реагировать объект.

В Java «интерфейс» также является артефактом, в котором определяются методы, на которые будет реагировать объект.

Итак, для стека вам нужно будет определить методы, которые имеет стек (интерфейс).

public interface Stack {
     public void push( Object o );
     public Object pop();
}

Затем используя наследование вы можете создать реализацию стека.Для этого вам придется расширить (или унаследовать) функциональность другого класса.Скажем, ArrayList

 /**
  * Sample stack implementation using inheritance
  */
public class ArrayListStack extends ArrayList implements Stack {
// you use the keyword extends because you're inheriting from ArrayList
// and the keyword implements because you claim to respond to push and pop methods.

     public void push( Object o ) {
          this.add( o ); // add inherited from ArrayList
     }
     public Object pop() {
         return this.remove( this.size() -1 ); // remove inherited from ArrayList
     }
}

Поскольку вы «наследуете» от ArrayList, большая часть того, что вам нужно, уже есть.Но представляет ли это отношения ЕС-А?Правда ли, что стек всегда является ArrayList?

Чтобы реализовать стек с помощью состав вам нужно «объединить» свой объект с другим.

  /**
   * Sample stack implementation using composition
   */ 
 public class ComposedStack  implements Stack {
      // you didn't extend anything here

      // But you'll need another object to help you 
      // to do the work.
      private ArrayList holder = .... // Should be declared as List holder = ....


    public void push( Object o ) {
         this.holder.add( o );
    }

    public Object pop() {
        return this.holder.remove( this.holder.size() -1 );
    }
 }

Реализация очень похожа: вы используете методы «добавить» и «удалить» из ArrayList.

Разница заключается в том, что в первом случае используется наследование вы не только используете эти два метода, но и полностью связываете свой объект с самим ArrayList (поскольку вы также наследуете все другие методы и атрибут, который имеет ArrayList)

Когда вы используете состав, вы не связываете свой объект со списком массивов (или связь низкая, и это хорошо). Вы просто используете другой объект, который поможет вам выполнить работу.В данном случае это был ArrayList.

Снаружи (используя композицию) вы не видите, что внутри находится ArrayList, который скрывает информацию.Пользователь (клиент) вашего класса видит только два доступных метода: «push» и «pop», и больше ничего нельзя сделать с вашим классом.Это похоже на «настоящий» стек.

При наследовании (с использованием ключевого слова Extensions) клиент класса также видит все методы из ArrayList хотя вы можете захотеть, чтобы использовались только pop и push, ничто не мешает клиенту использовать, например, «removeRange».

Заключение:Понимание различий между отношениями «есть» и «имеет» имеет важное значение для объектно-ориентированной технологии.Надеюсь, это вам поможет.

class stack
{

    int n,item,top;
    public stack()
    {
        n=7;
        top=-1;
    }}
    class student extends stack
    {
    int [] stk=new int[4];
    public void insert(int a)
    {
        if(top>=n-1)
        System.out.println("over flow");
        else
        {
            top++;
            stk[top]=a;
        }   
    }
        public void deletestk()
    {
        if(top<0)
            System.out.println("under flow");
            else
            {
                item=stk[top];
                top--;
                    System.out.println("deleted item are"+item);
            }
    }
        public void destroy()
    {
        if(top<0)
            System.out.println("under flow");
            else
            {

            top=-1;
    }
    }
    public void view()
    {
        int i;
        i=top;
        while(i>=0)
        {
                System.out.println(stk[i]);
                i--;
        }
    }   

    }
    class stackfloat extends stack
    {

        float [] stk=new float[6];
    }
    class stkstring extends stack
    {
        String [] stk=new String[5];
    }
    class stackmain
{
    public static void main(String arg[])
    {
        stack ob=new stack();
        student obj=new student();
            obj.deletestk();
        obj.insert(5);
            obj.insert(6);
                obj.insert(64);
                    obj.insert(45);
                        obj.insert(3);
                        obj.view();
                        obj.deletestk();
                        obj.view();
                        obj.destroy();
                        obj.view();



    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top