6.抽象与接口

6.1.抽象

       在第一章就有一个Shape类的例子。这个类有很多的子类,每个子类也都实现了父类的方法。实际上父类Shape只是一个抽象的概念而并没有实际的意义。如果请你画一个圆,你知道该怎么画;如果请你画一个矩形,你也知道该怎么画。但是如果我说:“请画一个形状,句号”。你该怎么画?同样,我们可以定义Circle类和Rectangle类的draw(),但是Shape类的draw()呢?

         Shape类表达的是一种概念,一种共同属性的抽象集合,我们并不希望任何Shape类的对象会被创建出来。那么,我们就应该把这个Shape类定义为抽象的。我们用abstract关键字来定义抽象类。抽象类的作用仅仅是表达接口,而不是具体的实现细节。抽象类中可以存在抽象方法。抽象方法也是使用abstract关键字来修饰。抽象的方法是不完全的,它只是一个方法签名而完全没有方法体。
         如果一个类有了一个抽象的方法,这个类就必须声明为抽象类。如果父类是抽象类,那么子类必须覆盖所有在父类中的抽象方法,否则子类也成为一个抽象类。一个抽象类可以没有任何抽象方法,所有的方法都有方法体,但是整个类是抽象的。设计这样的抽象类主要是为了防止制造它的对象出来。

在shape例子里有abstract的类及方法如下:

public abstract class Shape {
	
	public abstract void draw(Graphics g);
	
}

6.抽象与接口_第1张图片

shape没有存在的意义只是表达一种概念,draw方法也没有存在意义。

6.抽象与接口_第2张图片

实现抽象方法:

6.抽象与接口_第3张图片

两种抽象:

与具体相对:表示一种概念而非实体

与细节相对:表示在一定程度上忽略细节而着眼大局

 

6.2.数据与表现分离

细胞自动机:

6.抽象与接口_第4张图片‘’

6.抽象与接口_第5张图片

cellmachine:

package cellmachine;
import javax.swing.JFrame;

import cell.Cell;
import field.Field;
import field.View;

public class CellMachine {
	public static void main(String[] args) {
		//30*30的网格
		Field field = new Field(30,30);
		//在每个网格中放置cell对象
		for ( int row = 0; row");
					if ( cell.isAlive() ) {
						if ( numOfLive <2 || numOfLive >3 ) {
							cell.die();
							System.out.print("die");
						}
					} else if ( numOfLive == 3 ) {
						cell.reborn();
						System.out.print("reborn");
					}
					System.out.println();
				}
			}
			System.out.println("UPDATE");
			frame.repaint();
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

view:

package field;

import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;

import cell.Cell;

public class View extends JPanel {
	private static final long serialVersionUID = -5258995676212660595L;
	private static final int GRID_SIZE = 16;
	private Field theField;
	
	public View(Field field) {
		theField = field;
	}    
	@Override
	public void paint(Graphics g) {
		super.paint(g);
		for ( int row = 0; row

Data:Field/Cell

package field;

import java.util.ArrayList;
import cell.Cell;

public class Field {
	private int width;
	private int height;
	private Cell[][] field;	
	public Field(int width, int height) {
		this.width = width;
		this.height = height;
		field = new Cell[height][width];
	}
	
	public int getWidth() { return width; }
	public int getHeight() { return height; }
	
	public Cell place(int row, int col, Cell o) {
		Cell ret = field[row][col];
		field[row][col] = o;
		return ret;
	}
	
	public Cell get(int row, int col) {
		return field[row][col];
	}
	
	public Cell[] getNeighbour(int row, int col) {
		ArrayList list = new ArrayList();
		for ( int i=-1; i<2; i++ ) {
			for ( int j=-1; j<2; j++ ) {
				int r = row+i;
				int c = col+j;
				if ( r >-1 && r-1 && c
package cell;

import java.awt.Graphics;
 
public class Cell {
	private boolean alive = false;	
	public void die() { alive = false; }
	public void reborn() { alive = true; }
	public boolean isAlive() { return alive; }
	
	public void draw(Graphics g, int x, int y, int size) {
		g.drawRect(x, y, size, size);
		if ( alive ) {
			g.fillRect(x, y, size, size);
		}
	}
}

6.抽象与接口_第6张图片

6.抽象与接口_第7张图片

责任驱动设计:将程序要实现的功能分配到合适的类/对象中去是设计中非常重要的一环

网格化:

问题:

1、为什么不是在cell提供setAlive(Boolean)函数?而是采用复杂的die()、reborn()两个函数?

2、为什么filed.getNeighbour()不直接看cell.isAlive()来返回一个数字,而是要返回一个数组让外面来数数?

3、为什么不是cell自己判断自己的邻居的情况来决定自己是否应该die或reborn?

 

6.3.接口:狐狸和兔子

狐狸和兔子都有年龄

当年龄到了一定的上线就会自然死亡

狐狸可以随机决定在周围的兔子中吃一个

狐狸哥兔子可以随机决定吃一个小的,放在旁边的空的格子里

如果不吃也不生,狐狸和兔子可以随机决定向旁边空的格子移一步

cell类的地位很尴尬:

6.抽象与接口_第8张图片

6.抽象与接口_第9张图片

      从图中可得rabbit继承animal类和cell类,这是一种多继承,大多数的oop语言都不支持多继承(除c++外),因为多继承在实现上不好实现。

6.抽象与接口_第10张图片

若animal类与cell类相关联从语义上是不可行的,动物类和格子并没有确定的关系。但filed还需一个他认识的东西进行管理。

接口:

6.抽象与接口_第11张图片

6.抽象与接口_第12张图片

所以将cell定义为接口,fox和rabbit实现cell的接口。使用关键词implements

6.抽象与接口_第13张图片

因为cell是接口所以他不可能有对象,o的意思是任何实现了cell接口的对象(fox/rabbit)

实现接口:

6.抽象与接口_第14张图片

面对接口的编程方式:

6.抽象与接口_第15张图片

           Cell和Field的关系:cell在field中,但是cell的很多操作需要field的数据。方法一:让每个cell有一个filed的管理者(cell知道field)。方法二:有外部第三方来建立两者之间的联系(cell不知道filed)。

讨论

  1. cell要不要知道field? 在城堡游戏中,handler是知道game的;在细胞自动机中cell是不知道field的;
  2. 如果另外用一个ArrayList来表示所有的动物,每一步遍历这个列表而非整个ffield,这样做是否更好?(这样就需要每个animal知道自己在field里的位置)

 

 

 

你可能感兴趣的:(Java)