C#中has和is-aissn与isbn的区别别

继承(Is-A)还是聚合(Has-a)?这是一个问题 -
- ITeye技术网站
昨天遇见了一个问题,有人想实现一个常用的数据结构栈(Stack),基于链表的,于是在群里贴了一段代码:
public class Stack extends LinkedList {
public void push(Object object) { // 压栈
public Object peek() { // 获取栈顶元素
public boolean isEmpty() { // 判断栈是否为空
public Object pop() { // 弹栈
按照这种其实对应的实现代码很简单:
public class Stack extends LinkedList {
public void push(Object object) { // 压栈
add(0, object);
public Object peek() { // 获取栈顶元素
if (isEmpty()) {
return get(0);
public boolean isEmpty() { // 判断栈是否为空
return size()==0;
public Object pop() { // 弹栈
if (isEmpty()) {
return remove(0);
但是这样的设计合理吗?当面对继承和聚合不知道如何选择的时候,如何做出艰难的决定呢?
继承是一种Is-a关系,也就是说,如果当你要设计的类B在语义上可以说是A类的话,那么可以让B类继承A类,例如Cat(猫)是Animals(动物),我们就能让Cat extends Animals。而聚合是一种Has-a(包含)关系,当A要设计的B类在语义上包含另外一个类,并且在A在B中以整体的功能充当某个角色的时候,注意:很多时候,A类在B类外面是透明的。考虑使用聚合。例如,一只猫(Cat)有眼睛(Eyes)。那么可以设计成Cat类包含Eyes类,至于为什么A类在B类外是透明的,如下:
public class Cat {
public Cat(Eyes eyes) {
this.eyes =
public void see() {
eyes.see();
public class Eyes {
public void see() {
System.out.println("see");
在使用Cat类对象时,并不需要关注其内部对于see()方法的实现,很明显的猫也不是眼睛(不是Is-a关系),再来看前面的问题,栈并不是一个链表,所以采用继承的方式是不合适的,继承之所以是Is-a关系,是因为它继承了父类全部的方法,即它拥有了父类所有的行为。在上面的继承实现栈的方法中,栈继承了链表的所有方法,这样你就不能保证栈的特性—first in last out(先进后出)了。因为它同时也是链表,可以调用其从父类继承的方法在任一位置做删除和插入。下面是一种更好的has-a实现方式:
public class Stack {
public void push(Object object) { // 压栈
list.add(0, object);
public Object peek() { // 获取栈顶元素
if (isEmpty()) {
return list.get(0);
public boolean isEmpty() { // 判断栈是否为空
return list.size()==0;
public Object pop() { // 弹栈
if (isEmpty()) {
return list.remove(0);
这个时候栈对外的表现就纯粹的是栈了,因为它只具有栈的行为。至于里面是如何实现的,用户无需关心,同时也是安全的,用户除了入栈出栈之外,无法做其他的删除插入操作,这里选用了List作为其属性,没有限制用户使用ArrayList或者LinkedList,其实可以使用Collection属性,用户的选择就更大了。当然也能使用数组。可见对外表现一致的栈,其内部实现可以多样化,即在has-a关系中A类在B类外面是透明的. 在利用List实现时你也可以采用与上面不同的策略:每次取出列表的最后一个元素,将元素入栈时加入列表的最后一个位置。
现在你可以做出艰难的决定了。简单地说,如果在语义上你能说B是A,那么采用继承,否则使用聚合。聚合使用的场合会多一些。
继承也能是has-a,聚合也能使Is-a
如果B类继承了A类,毫无疑问的,B类具有了A类的所有行为,在逻辑上B类其实Has A了。其中super关键字就表示了一个类的父类对象引用,可见说继承是一种has-a的关系逻辑上是没有错误的。为什么继承不能完全的替代has-a关系呢?这是因为继承时,继承需要行为的时候将不需要的行为,甚至是不能出现的行为,如上文链表的任意位置的插入删除行为也继承了下来。java只有一种继承方式,这源自java的设计哲学“C++ --”。在C++中有更多样的继承方式,其中的一种继承就是一种完全的has-a关系而非Is-a关系----私有继承。B类私有继承自A类则将A类中的所有行为全部继承为B类自己的私有行为,这样B类对外再也不能表现出A类的行为,是一种完全的has-a关系。
当然has-a关系也能体现出Is-a的关系,这来自用户的设计,可以在B类中定义所有A类的方法,然后内部调用A类实例去实现,这样B类就能对外表现A类的所有行为了。当然拥有A的同名方法未必能对外表现为B。除非你同时继承A,等等……是不是有点乱了。
B类继承A类,B类还包含A类的实例(A a = new A())。这样在B中不是有两个A的实例了一个是super一个是a。确实是这样。但是如果A是一个接口呢?
B实现了接口A,然后B类中中还有一个实现A的类的实例:
这样B对外可以作为A使用,而对内调用a的方法来进行实际的操作,B好像什么也没有做啊?不是什么也没有做,B做了代理,这就是我们常说的代理模式。
(未完不知道续不续)
浏览: 1205 次
来自: 长沙维基百科,自由的百科全书
在、與的領域裡,is-a(:subsumption,包含架構)指的是類別的父子繼承關係,例如類別D是另一個類別B的(類別B是類別D的)。
換句話說,通常"D is a B"(B把D包含在內,或是D被包含在B內)指的是,概念體D物是概念體B物的,而概念體B物是概念體D物的。舉例來說,是、、與其他水果的一般化。
在裡,is-a類別關係是在概念的背景之下所形成的。有一說法是,對於所有水果來說,繼承(:inherit)所有的屬性,就像是肉質多的水果包住種子般。
is-a與兩者是不同的對比,是以-階層關係所組成的。也可以是的對比:請參考。
在真實世界裡設計一個模型時(例如),尤其是物件與它的下一層從屬物件,在has-a與is-a兩者的關係上容易產生概念上的錯誤。
; . IEEE Computer, 16 (10); October 1983
Jean-Luc Hainaut, Jean-Marc Hick, Vincent Englebert, Jean Henrard, Didier Roland: . ER
 Is-a是一個與相關的。你可以通过擴充其內容。
:隐藏分类:A和B如果是is-a 的关系,那么使用继承。如果 是has-a,就应该是两个独立的类, 将所有类型的B封装成一个类, 通过setter设为A的一个属性,就是Strategy了, 这样可以在运行时视情况改变a的行为了。如果想在原有类的一个实例中动态增加属性或者做处理, 使用Decorator层层修饰,就象Inputstream一样。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:9496次
排名:千里之外
原创:20篇
(1)(11)(3)(1)(2)(4)C#类、接口、虚方法和抽象方法_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
2页免费4页2下载券8页1下载券5页免费3页2下载券34页1下载券2页免费30页1下载券6页1下载券4页1下载券
喜欢此文档的还喜欢2页免费30页5下载券2页1下载券5页免费34页1下载券
C#类、接口、虚方法和抽象方法|不​看​,​你​后​悔​!​…​…
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢1091人阅读
public class B : A
public class Man
private Heart heart = new Heart();
class Course
public class Student
public void Learn(Course course)
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:29309次
排名:千里之外
原创:36篇
评论:14条
(1)(2)(6)(9)(4)(2)(9)(4)

我要回帖

更多关于 issn与isbn的区别 的文章

 

随机推荐