你的概念是颠倒的。
继承,顾名思义,就是从现有对象中“获取”功能。这被称为 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 技术至关重要。希望对您有所帮助。