点击这里给我发消息 点击这里给我发消息

设计类

添加时间:2013-12-7
    相关阅读: 设计 程序 框架
 

在面向对象程序设计中,一个基本的问题就是决定在你的程序中各个类之间的相互关系。一种可能性是从你已经定义的基类派生出若千个类来,以建立一个类的结构层次,并为特定的子类增加方法和数据成员。我们的Animal类和由它派生出来的子类就是这样一个例子。另一种可能性是定义一套类,它们没有结构层次关系,但是,有一些属于它们自己的类对象的数据成员。例如,Zoo类可能就有一个从Animal类派生的类对象作为成员。你可以有包含数据成员为类对象的类结构,其实我们已经在类Animal中接触过这种情况,它有一个String类型的成员。到目前为止,这些例子选择的方式都比较明确,但并不是总会这样地明显。你常常需要在把一个类作为层次结构中的一个类定义,还是作为一个类对象的成员的类定义之间进行选择。采用哪种方式最好呢?

与所有这类问题一样,没有一个明确的答案。如果面向对象程序设计是一个过程,而这个过程可以通过你只需盲目遵守的一套固定的规则来进行说明,那么我们就可以把它提交给计算机完成这些事情。尽管有一些准则,但可能解答中的内容可能更明显。

除了反映对象类型之间的现实世界关系的需求以外,使用多态性(或者我们在不久就会看到的接口)也是使用子类的一个主要原因。这是面向对象程序设计的精华,能够被等效处理的一堆相关的对象可以极大地简化你的程序。你已经看到如何从一个公共的基类Animal派生出来的类获得指定的各种动物类型,这将使我们可以对不同类型的动物进行处理,而它们就好像是同一种类型。产生的不同结果将取决于目前正在处理的动物类型,所有这些完全都是自动地。

一个漂亮的例子

许多场合都涉及到要对你的类设计做出判断。判断的方式可能最终归结为人们的偏爱。让我们思考一个简单的例子,试试看如何实际地进行选择。假设我们想定义一个类PolyLine,用来描述由多条相连的线段组成的折线,如下图所示。

这个示意图显示了两条折线,一条由4个点定义;另一条由7个点定义。

使用Point类对象描述点似乎比较合适。被定义好的点对象将会出现在各类几何体中。我们把前面看到的点类放置在Geometry包中。我们需要在此定义框架,而不是重复所有的东西。

public class Point

{

   //create a point from its coordinates

   public Point(double xVal,double yVall

   {

      x=xVal;

      y=yVal;

}

你可以有三种方式定义ListPaint类,并且有相应的三种自变量来支持。

你可以用显式存储的x和Y定义ListPoint类。对应这种定义的主要自变量已经被囊括在Point类的点属性中,我们为什么不使用它呢?

我们可以把ListPoint对象当作包含一个对Point对象的引用,加上对链表中前驱和后继对象的引用的东西。这并非是不合理的途径。它很容易实现,并且与ListPoint的直觉概念不相矛盾。

你可以把一个ListPoint对象看成是一种特定的Point类型,因此,可以从Point类 派生出ListPoint类。究竟这样做是否合适将取决于你是否把它认为是合法的。我 的想法是进一步延伸点概念的用途,因此,我们不这样使用。

最好的选择看来是第二种方式。我们可以利用一个Point类型的数据成员实现ListPoint类,Point利用点的坐标定义一个基本的点。ListPnint对象还有一个额外的数据成员next.它是ListPoint类型的,并且链表中的每个对象,除最后一个对象外,next都将包含链表中下一个对象的引用。链表中的最后一个对象的变量next为null。

试试看——ListPoint类

我们可以通过类Point使用线面的代码定义ListPoint类:

public class ListPoint

{

  //constructor

  public ListPoint(Point point)

   {

     this.point=point;                                 //store point reference

     next=null;                                        //Set next ListPoint as null

}

  //Set the pointer to the nex ListPoint

  public void setNext(ListPoint Next)

   {

      this.next      next;                     //store the next ListPoint

 }

//Gat the next point in the list

public ListPoint getNext()

{

   return next;                //Return the next ListPoint

)

  //Return string pepreesentation

  public string tostring()

  {

    return *{* + point+);

  private LisPoint next;          //Refers to next ListPoint in the list

  private Point point;            //The point for this list point
 
如何操作

ListPoint对象是建立Point对象序列的一种方式,这些Point对象位于其他的位置,因此,不必担心在链表中会出现重复的Point对象。我们可以只在数据成员point中存储传递给构造函数的Point对象的引用。数据成员next应该包含链表中下一个ListPoint的引用,由于在此我们还没有定义,所以把next设置为null.

当把一个新的点添加到序列中时,SetNext()方法可以为现存的最后一个点设置next数据成员。这个新的ListPoint对象的引用将作为自变量传递给该函数。GetNext()方法可以确定链表中的下一个点,因此,这个方法可以用来遍历整个链表。

若要为这个类实现tostring (),我们就可以在必要的时候,自动地为ListPoint对象建立一个String型的描述。这里,我们把point的String描述包含在括号之间以区别于ListPoint对象的String描述。

我们现在可以开始尝试实现PolyLine类。

试试看--PolyLine类

我们可以利用ListPoint类定义PolyLine类,定义如下;

public class PolyLine

{

  //construct a polykine from array of points

  public PolyLine(Point[] points)

  {    

   if(points !=null)            //Make sure there is an array

   {

   //create a one point list

   start=new ListPoint(points[0];     //lst point is the start

   end=start;                         //as well as the end

   //Now add rhe other points

   for (int i=1;i<point.longth;i++)

      addPoint(points(i));

  )

)

//Add a point object to the list

public void addPoint(Point point)

{

  ListPoint newEnd =new ListPoint(point);     //Create a new listpoint

  if(start==null!

  start=newEnd;                               //start is same as end

  else

   end.setNext(newEnd);                     //set next variable for old end as new end

  end=newEnd;                                    //store new point as end

)

  //string represetation of a polyline

public string tostring()

{

  stringBuffer str-new stringBuffer(Polyline)

  ListPoint nextPoint=start;                 //ser the lst puint as  start

  while(nextPoint !=null)

 {

 str.append(nextPoint);                //output current point

 nexPoint=nextpoint.getNext();         //Make the point current

}

  return str.tostring()

}

  private listpoint start;           //first listpoint in the list

private listpoint end;               //Last ListPoint in the list
 
你可能希望这个类具有指定一对坐标,向序列中添加一个点的能力。你可以重载addPoint()方法来完成这项操作。

我们用表达式建立一个新的Point对象,并作为自变量传递给另一个版本的addPoint().

你可能还想要由一个坐标数组建立一个PolyLine对象。完成这个操作的构造函数是:

//Add a point to the list

publicvoid addpoint(double x,double y)

{

 addpoint(new point(x,y));

}

我们用表达式建立一个新的Point对象,并作为自变量传递给另一个版本的addPoint().你可能还想要由一个坐标数组建立一个PolyLine对象。完成这个操作的构造函数是:

// Construct a polyline from an array of coordinate

public PolyLine(double[][]coords)

 {

   if(coords !=null)

 {

   //Create a one point list

   start=new ListPoint(new point(coords[0][0],coords[0][1]);

                                    //First is start

end=start;                      //as well as end

//New add the other points

for(int i=1;i<coords.length;i++)

   addPoint(coords[i][0].coords[i][l]};

  }

 }
 
如何操作

PalyLine类有我们在示意图中看到的两个数据成员start和end.它们将引用序列中的第一个点和最后一个点,如果序列为空,它就为null.构造函数接收一个Point对象的数组,并且启动装配对象的过程,即首先建立一个包含由数组中第一个元素生成的ListPnint对象,然后再使用方法addPoint()把数组中其余的所有点添加进去。

把点添加到序列中出人意料地简单。所有的addPoint()方法都要首先利用自变量传递过来的Point对象建立一个ListPoint对象,然后设置序列中刚才的最后一个点的next成员内容,让它引用这个新点,最后,再把新的最后一个点的引用存储在end成员中。

方法tnString()同点坐标序列一样返回Po吵pint对象的字符串描述。注意,ListPoint对象next成员如何控制循环遍历这个序列。当到达最后一个点时,next成员将返回null,此时while循环结束。

现在,我们可以尝试着给出PolyLine类。

咨询热线:020-85648757 85648755 85648616 0755-27912581 客服:020-85648756 0755-27912581 业务传真:020-32579052
广州市网景网络科技有限公司 Copyright◎2003-2008 Veelink.com. All Rights Reserved.
广州商务地址:广东省广州市黄埔大道中203号(海景园区)海景花园C栋501室
= 深圳商务地址:深圳市宝源路华丰宝源大厦606
研发中心:广东广州市天河软件园海景园区 粤ICP备05103322号 工商注册