【问题标题】:java inheritance versus composition (implementing a stack)java继承与组合(实现堆栈)
【发布时间】:2009-09-13 23:32:28
【问题描述】:

我正在尝试在 java 中实现一个堆栈(使用列表接口:Interface List)。

我想以两种不同的方式实现它:使用组合和继承。

对于继承,到目前为止我有:

 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。在不完全理解接口以及继承和组合之间,我有点迷茫。我似乎还不能“明白”...

任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: java inheritance list stack composition


    【解决方案1】:

    对于组合,堆栈类应该有一个列表,而不是实现或扩展基于列表的类。继承是“IS A”关系,而组合是“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 作为内部数据结构的面孔。使用组合 List 可以完全隐藏使用 List 作为内部结构的事实。

    【讨论】:

    • 安迪-感谢您的帮助。我明白你的意思了,现在。我已经用继承和组合实现了堆栈。我看到所有必须包含在继承中的原始 List 方法,对于堆栈而言,这些方法没有意义。谢谢:)
    【解决方案2】:

    我认为这不是一个真正的问题。这是一个“你能为我做作业吗”的问题。

    更有意义的问题是:

    • 继承和组合有什么区别?
    • 分别实现堆栈的优点/缺点是什么?
    • 什么是堆栈?

    安迪对这三个问题都给出了很好的答案。

    不幸的是,看起来原始发帖人的老师自己也不太了解这些概念,因为作业是荒谬的。实现 java.util.List 的类不是堆栈,或者更确切地说,用作堆栈是不安全的,因为它要求非堆栈安全操作是公共的。堆栈是一个比列表更具限制性的接口。

    难怪原发帖人一头雾水。

    【讨论】:

      【解决方案3】:

      你的概念是颠倒的。

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

      在您的第一个示例中,这不是继承,因为您没有从列表中获取任何内容。在您的示例中,您正在“实施”该列表而不是“扩展”它。

      组合是指您使用其他对象构建对象(您正在组合对象)。这被称为 HAS-A 关系。例如 Truck HAS-A 车轮(但不是车轮)。在您的示例中,您正在从其他对象“扩展”(继承)

      最后,OOP 中的 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 是真的吗?

      要使用 composition 实现堆栈,您必须将您的对象与另一个对象“组合”。

        /**
         * 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 中的“添加”和“删除”方法

      不同之处在于,在使用 inheritance 的第一种情况下,您不仅使用这两种方法,而且将对象完全耦合到 ArrayList 本身(因为您还继承了所有其他方法, 以及 ArrayList 具有的属性)

      当你使用 composition 时,你不会将你的对象耦合到 arraylist (或者耦合很低,这是一件好事)你只是在使用另一个对象来帮助你做工作。在这种情况下,它是一个 ArrayList。

      从外面看(使用组合),你看不到里面有一个 ArrayList,那是信息隐藏。您班级的用户(客户)只能看到两种可用的“push”和“pop”方法,并且您的班级没有什么可以做的了。它看起来像一个“真正的”堆栈。

      通过继承(使用 extends 关键字),类的客户端也可以看到来自ArrayList 的所有方法,尽管您可能希望只使用 pop 和 push,但没有什么能阻止客户端使用例如“removeRange”。

      结论:了解 is-a 和 has-a 关系之间的区别对于 OO 技术至关重要。希望对您有所帮助。

      【讨论】:

        【解决方案4】:
        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();
        
        
        
            }
        }
        

        【讨论】:

          【解决方案5】:

          java中的组合是实现has-a关系的设计技术

          【讨论】:

          • 感谢您的回复,但请您回复详细和规范,以便用户知道如何以及为什么使用它。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-11-11
          • 2011-05-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-24
          相关资源
          最近更新 更多