java 继承与组合(实现堆栈)
-
07-07-2019 - |
题
我正在尝试在java中实现一个Stack(使用列表接口: 接口列表).
我想以两种不同的方式实现它:使用组合和继承。
对于继承,到目前为止我有:
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 中。在不完全理解接口以及继承和组合之间,我有点迷失。我似乎还不能“明白”......
任何帮助将不胜感激,谢谢!
解决方案
对于组合,堆栈类应该有一个列表,而不是实现或扩展基于List的类。继承是“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.
}
请注意,您可能希望将其设为泛型类,而不是处理原始对象,但这可能就是这个想法。
在这种情况下,基于组合的解决方案可能优于基于继承的解决方案。当你从类/接口继承时,你应该问自己,Stack是List吗?大多数Stacks不应该为用户提供对所有原始List方法的访问权限,因此最好隐藏您正在使用List作为内部数据结构的面。使用组合列表可以完全隐藏您使用List作为内部结构的事实。
其他提示
我认为这不是一个真正的问题。这是一个“你能帮我做作业吗”的问题。
更有意义的问题是:
- 继承和组合有什么区别?
- 分别实施堆栈的优点/缺点是什么?
- 什么是堆栈?
安迪对这三个人都给出了很好的答案。
不幸的是,看起来原发帖者的老师自己也不太理解这些概念,因为作业是无意义的。实现 java.util.List 的类不是堆栈,或者更确切地说,用作堆栈是不安全的,因为它要求非堆栈安全操作是公共的。堆栈是比列表更具限制性的接口。
难怪原海报很混乱。
你的概念是颠倒的。
继承,正如所说的那样,当你“采取”从现有对象的功能。这被称为IS-A关系。例如,卡车 IS-A 车辆。
在你的第一个不是继承的样本中,因为你没有从列表中取任何东西。在您的示例中,您正在“实施”该列表不是“扩展”的它。
组合是指使用其他人构建对象(您正在组合对象)。这被称为HAS-A关系。例如卡车 HAS-A 车轮(但不是车轮)。在您的样本中,您正在“扩展” (继承)来自其他对象
最后,OOP中的接口是“合同”。一个对象被承诺履行。对象将响应哪些函数或消息。
在Java“界面”中也是一个工件,其中定义了对象将响应的方法。
因此,对于堆栈,您必须定义Stack具有的方法(接口)
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。
从外部(使用组合),你没有看到里面有一个ArrayList,这是信息隐藏。您班级的用户(客户)只能看到两种可用的方法“推送”。和“流行”你的班级没有什么可以做的。它看起来像一个“真实的”栈。
使用继承(使用extends关键字),类的客户端也可以看到 ArrayList 虽然你可能只想使用pop和push,但是没有什么能阻止客户端使用”removeRange“。例如。
结论:理解is-a和has-a之间的差异对于OO技术至关重要。我希望这能帮到你。
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();
}
}