Java继承与组合(实现堆栈)

4
我将尝试在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吗?
另外,对于组合(composition),我不知道应该将哪些方法放入StackComposition中,哪些应该放入StackViaList中。由于对接口、继承和组合的理解还不够,我有点迷茫。目前看来好像无法完全“get it”…
谢谢大家提供帮助!
5个回答

9

对于组合而言,栈类应该拥有一个列表,而不是实现或扩展基于列表的类。继承是一种“是一个”关系,而组合是一种“有一个”关系。

例如:

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.
}

请注意,您可能希望将其制作为通用类,而不是处理原始对象,但这将是想法。
在这种情况下,基于组合的解决方案可能比基于继承的解决方案更可取。当您从类/接口继承时,您应该问自己,Stack是List吗?大多数Stacks不应向用户提供对所有原始List方法的访问权限,因此最好隐藏使用List作为内部数据结构的事实。使用组合的List允许您完全隐藏使用List作为内部结构的事实。

Andy-感谢您的帮助。我现在明白您的意思了。我已经使用继承和组合两种方式实现了堆栈。我发现继承需要包含所有原始列表方法,而这对于堆栈来说是没有意义的。谢谢 :) - littleK

2
我认为这不是一个真正的问题。这是一个“你能帮我做作业吗”的问题。
更有意义的问题可能是:
- 继承和组合之间有什么区别? - 使用它们实现堆栈的优缺点是什么? - 什么是堆栈?
Andy对这三个问题都给出了很好的答案。
不幸的是,原帖的老师似乎自己并不太理解这些概念,因为这个作业是没有意义的。实现java.util.List的类不是一个堆栈,或者说,它不安全地使用作为堆栈,因为它需要将非堆栈安全操作公开。堆栈是一个比列表更加限制的接口。
难怪原帖的作者感到困惑。

1

你的概念是颠倒的。

继承,顾名思义,就是从现有对象中“取出”功能。这被称为IS-A关系。例如,卡车IS-A车辆。

在你的第一个示例中,这不是继承,因为你没有从列表中取任何东西。在你的示例中,你正在“实现”该列表而不是“扩展”它。

组合是指使用其他对象构建对象(即组合对象)。这被称为HAS-A关系。例如,卡车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“继承”,因此大部分所需内容已经存在。但是,这是否代表了IS-A关系?堆栈始终是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 的 "add" 和 "remove" 方法。
不同之处在于,在第一种情况下使用继承,你不仅使用这两个方法,而且完全将你的对象与 ArrayList 本身耦合(因为你还继承了 ArrayList 拥有的所有其他方法和属性)。
当你使用组合时,你不会将你的对象与数组列表耦合在一起(或者耦合程度很低,这是一件好事),你只是使用另一个对象来帮助你完成工作。在这种情况下是 ArrayList。
从外部(使用组合)来看,你看不到 ArrayList 的内部,这就是信息隐藏。你的类的用户(客户端)只看到两个可用的方法 "push" 和 "pop",并且没有其他可以在你的类上执行的操作。它看起来像一个 "真正的" 栈。
使用继承(使用 extends 关键字),类的客户端也可以看到 ArrayList 的所有方法,尽管你可能希望仅使用 pop 和 push,但客户端可以使用 "removeRange" 等其他方法。
结论:了解 is-a 和 has-a 关系的区别对于面向对象技术至关重要。希望这可以帮助您。

0
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();



    }
}

-1

Java中的组合是实现具有关系的设计技术


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接