наследование Java против композиции (реализация стека) - PullRequest
3 голосов
/ 14 сентября 2009

Я пытаюсь реализовать стек в 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. Между не совсем пониманием интерфейсов, а также наследования и композиции я немного растерялся. Я пока не могу просто "получить это" ...

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

Ответы [ 4 ]

9 голосов
/ 14 сентября 2009

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

Например:

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 в качестве внутренней структуры данных. Использование составного списка позволяет полностью скрыть тот факт, что вы используете список в качестве внутренней структуры.

2 голосов
/ 07 октября 2009

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

Более значимые вопросы:

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

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

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

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

1 голос
/ 07 октября 2009

У вас есть концепции с ног на голову.

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

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

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

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

В 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, большая часть того, что вам нужно, уже есть. Но представляет ли это отношение IS-A? Правда ли, что Stack IS-An 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», и больше ничего нельзя сделать с вашим классом. Это похоже на «настоящий» стек.

С наследованием (используя ключевое слово extends), клиент класса также видит все методы из ArrayList , хотя вы можете захотеть использовать только pop и push, ничто не мешает клиенту использовать "removeRange" " например.

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

0 голосов
/ 09 февраля 2011
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();



    }
}
...