面向对象的实现
对象之间存在的关系如下:
继承关系
继承关系使用extends关键字来实现,通常父类具有的属性子类都有,另外子类会有一些特殊的属性,继承父类之后,只需要在子类中添加新的成员变量就可以了。
这里需要关心的是这些成员变量在哪里进行初始化?对于子类新创建的成员变量肯定是在子类中就行初始化,通常情况下是在构造函数中进行初始化。对于从父类继承过来的成员变量可以在父类中初始化,也可以在子类中进行初始化,如果是在父类的构造函数中初始化,需要在子类的构造函数中调用父类的构造函数,如果调用默认的构造函数子类中可以不显式调用。
public class A
{
private int a;
public A()
{
a = 0;
}
public A(int a)
{
this.a = a;
}
}
一个成员变量,两个构造函数,第一个赋默认值0,第二个赋给定的值。
public class B extends A
{
private int b;
public B()
{
b = 0;
}
public B(int a,int b)
{
super(a);
this.b = b ;
}
public void setB(int b)
{
this.b = b;
}
public int getB()
{
return b;
}
}
无参数的构造函数是默认的构造函数,实际上在初始化的时候调用了父类的无参数构造函数,第二个构造函数通过关键字super显式的调用了父类的构造函数。
一对一的关系
一对一的关系,例如A和B两个之间的关系就是一对一的关系,每个A要么对应一个B要么不对应B,而每个B要么对应一个A要么不对应。
一对一的关系使用Java来实现,需要把一个类的对象作为另外一个类的成员变量,一对一的关系可以是双向的,可以是单向的,主要根据需要来确定,如果仅仅需要根据一个对象找到另一个对象,这种关系就是单向的,如果需要根据任意一方找到另外一方,这种关系就是双向的。
假设A和B是一对一的关系,并且这种关系是单向的,只需要根据A定位B,关系的定义如下:
public class A
{
public B b;
public void setB(B b)\
{
this.b = b;
}
public B getB()
{
return b;
}
}
如果是关联关系,b仅仅是引用,A和B的关联通常会有下面的代码:
A a1 = new A();
B b1 = new B();
a1.setB(b1);
从上面的代码可以看出,这种关联关系应该是先有对象存在,然后通过set方法来建立这种关系。
如果是包含关系,这种关系的建立通常是在创建包含对象的时候创建,也就是说通常会在构造函数中编写,也就是说当组件存在的时候,才去创建整体,当然这不是绝对的。
如果是包含关系,首先类的代码可能是这样的:
public class A
{
public B b;
public A(B b)
{
this.b = b;
}
public void setB(B b)
{
this.b = b;
}
public B getB()
{
return b;
}
}
对象创建的代码可能是下面的样子:
B b=new B();
A a = new A(b);
把B的对象作为参数来创建A的对象。
如果是双向关系,这时候只能是关联关系,不能是包含关系,类的定义需要定义成如下的形式:
public class A
{
B b;
public void setB(B b)
{
this.b = b;
}
public B getB()
{
return b;
}
}
public class B
{
A a;
public void setA(A a)
{
this.a = a;
}
public A getA()
{
return a;
}
}
关系的建立通过下面的代码:
A a1 = new A();
B b1 = new B();
a1.setB(b1);
b1.setA(a1);
这里需要注意的是两个对象之间并不是包含关系,有人会说A是B的成员变量,B又是A的成员变量,就像鸡和蛋的问题,到底应该是先有A还是先有B。其实,可以这样去想,学过C或者C++的人都知道指针,在这里是引用,可以理解为相互引用,是对象的引用作为成员,而不是对象作为成员。
另外需要注意的是因为A作为B的成员变量,B又作为A的成员变量,在编译A的时候会用到B,同时在编译B的时候会用到A,没有办法单独编译,所以如果是这种双向关系,需要同时编译。使用:
javac *.java
关系的访问,可以根据一个对象访问与它相关联的对象,例如有A的对象a1,可以访问与a1关联的B的对象,不管是关联关系还是包含关系,访问的方法是相同的:
B temp = a1.getB();
//temp指向a1关联的对象,这样访问temp就可以了。
一对多的关系
一对多的关系需要定义集合类型的对象作为成员变量:假设A和B是一对多的关系。
public class A
{
Collection bs;
//设置元素的方法
public A
{
bs = new ArrayList();
}
public void setBs(Collection c)
{
bs = c;
}
//获取元素的方法
public Collection getBs()
{
return bs;
}
//添加元素的方法
public void addB(B b)
{
if(bs==null)
bs = new ArrayList();
bs.add(b);
}
public void removeB(B b)
{
if(bs!=null)
bs.remove(b);
}
}
public class B
{
A a;
public void setA(A a)
{
this.a = a;
}
public A getA()
{
return a;
}
}
如果是包含关系,通常不需要在B类中创建与A对象的关联。
关系的建立与操作:
A a1 = new A();
//创建A的对象
for(int i=1;i<5;i++)
{
B temp = new B();
//创建B的对象
temp.setA(a1);
//建立B对象与A对象之间的关系
a1.addB(temp);
//建立A对象与B对象之间的关系
}
关系的访问,一对多的关系的访问要稍微复杂一些。B中访问A的过程与前面的一对一情况相同,通过A访问B的代码如下:
Object[] bs = a1.getBs().toArray();
//对关联的对象进行遍历
for(int i=0;i<bs.length;i++)
{
B temp=(B)bs[i];
//temp指向某个元素,进行操作就可以了
System.out.println(temp.toString());
//这里a1所关联的所有对象的信息显示在控制台
}
多对多的关系
多对多的关系只能是关联关系,如果只考虑单向关系,与一对多的关系相同,所以这里介绍的是双向关系。
多对多的关联关系的定义如下:
public class A
{
Collection bs;
//设置元素的方法
public A
{
bs = new ArrayList();
}
public void setBs(Collection c)
{
bs = c;
}
//获取元素的方法
public Collection getBs()
{
return bs;
}
//添加元素的方法
public void addB(B b)
{
if(bs==null)
bs = new ArrayList();
bs.add(b);
}
public void removeB(B b)
{
if(bs!=null)
bs.remove(b);
}
}
public class B
{
Collection as;
//设置元素的方法
public B
{
as = new ArrayList();
}
public void setAs(Collection c)
{
as = c;
}
//获取元素的方法
public Collection getAs()
{
return as;
}
//添加元素的方法
public void addA(A a)
{
as.add(a);
}
public void removeA(A a)
{
if(as!=null)
as.remove(a);
}
}
关系的建立比较复杂,假设有5个A的对象,有4个B的对象,它们的关系如下:
a1
|
a3
|
a2
|
b1
|
b3
|
b2
|
这些关系的建立,需要下面的代码:
A a1 = new A();
A a2 = new A();
A a3 = new A();
A a4 = new A();
A a5 = new A();
//A对象的创建
B b1 = new B();
B b2 = new B();
B b3 = new B();
B b4 = new B();
//B对象的创建
a1.add(b2);
a2.add(b1); a2.add(b3);
a3.add(b1); a3.add(b2); a3.add(b3);
b1.add(a2); b1.add(a3);
b2.add(a1); b2.add(a3);
b3.add(a2); b3.add(a3);
//关系的创建
多对多的关系的访问与前面一对多的关系的访问基本相同,这里不再给出代码。