Java学习笔记(六)——抽象与接口

1、抽象

抽象函数——能表达出概念而无法实现具体代码的函数

抽象类——能表达出概念而无法实现具体代码的类

抽象函数和抽象类的注意点:

  • 带有abstract修饰符的函数
  • 有抽象函数的类一定是抽象类
  • 抽象类不能制造对象,但是可以定义变量,任何继承了抽象类的非抽象类的对象可以赋给这个变量

!继承自抽象类的子类必须覆盖父类的抽象函数!

举个栗子

//Shape.java
package shapes;

import java.awt.Graphics;

public abstract class Shape {
	
	public abstract void draw(Graphics g);
	
}
//Line.java
package shapes;

import java.awt.Graphics;

public class Line extends Shape {
	private int x1;
	private int y1;
	private int x2;
	private int y2;
	
	public Line(int x1, int y1, int x2, int y2)
	{
		this.x1 = x1; this.y1 = y1;
		this.x2 = x2; this.y2 = y2;
	}
	
	@Override
	public void draw(Graphics g) {//要覆盖Shape抽象类的draw函数
		g.drawLine(x1, y1, x2, y2);
	}

}

 

2、数据与表现分离(一个细胞自动机的例子)

思想都在代码里体现

代码运行之后是酱紫的~

//Cell.java
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);
		}
	}
}
//Field.java
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) {// 获得一个细胞的八个邻居,返回一个Cell数组
		ArrayList<Cell> list = new ArrayList<Cell>();
		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 < height && c > -1 && c < width && !(r == row && c == col)) {
					list.add(field[r][c]);
				}
			}
		}
		return list.toArray(new Cell[list.size()]);
	}

	public void clear() {
		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				field[i][j] = null;
			}
		}
	}
}
//View.java
package field;

import java.awt.Dimension;
import java.awt.Graphics;

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;// 初始化设定表格大小为16
	private Field theField;

	public View(Field field) {// View的构造函数
		theField = field;
	}

	@Override
	public void paint(Graphics g) {// View只需要把field画出来就行,不需要管数据,这就是数据和表现分离的体现
		super.paint(g);
		for (int row = 0; row < theField.getHeight(); row++) {
			for (int col = 0; col < theField.getWidth(); col++) {
				Cell cell = theField.get(row, col);
				if (cell != null) {
					cell.draw(g, col * GRID_SIZE, row * GRID_SIZE, GRID_SIZE);
				}
			}
		}
	}

	@Override
	public Dimension getPreferredSize() {
		return new Dimension(theField.getWidth() * GRID_SIZE + 1, theField.getHeight() * GRID_SIZE + 1);
	}

	public static void main(String[] args) {

	}

}
package cellmachine;

import javax.swing.JFrame;

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

//CellMachine.java
public class CellMachine {

	public static void main(String[] args) {
		Field field = new Field(30, 30);// 设定长宽各30个格子
		for (int row = 0; row < field.getHeight(); row++) {
			for (int col = 0; col < field.getWidth(); col++) {
				field.place(row, col, new Cell());// 初始化表格,默认细胞都是死亡状态
			}
		}
		for (int row = 0; row < field.getHeight(); row++) {
			for (int col = 0; col < field.getWidth(); col++) {
				Cell cell = field.get(row, col);
				if (Math.random() < 0.2) {// 初始化:细胞有1/5的概率能重生
					cell.reborn();
				}
			}
		}
		View view = new View(field);
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		frame.setTitle("Cells");
		frame.add(view);
		frame.pack();
		frame.setVisible(true);//要能显示出来

		for (int i = 0; i < 1000; i++) {
			for (int row = 0; row < field.getHeight(); row++) {
				for (int col = 0; col < field.getWidth(); col++) {
					Cell cell = field.get(row, col);
					Cell[] neighbour = field.getNeighbour(row, col);//得到邻居数组
					int numOfLive = 0;
					for (Cell c : neighbour) {//统计邻居活细胞数
						if (c.isAlive()) {
							numOfLive++;
						}
					}
					System.out.print("[" + row + "][" + col + "]:");
					System.out.print(cell.isAlive() ? "live" : "dead");
					System.out.print(":" + numOfLive + "-->");
					if (cell.isAlive()) {
						if (numOfLive < 2 || numOfLive > 3) {//如果邻居活细胞数不为3那么就要die
							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();
			}
		}
	}

}

 

3、接口

接口是纯抽象类,意思是它其中所有的函数都是抽象函数所有的成员变量都是public static final

接口规定了长什么样,但是不管里面有什么

接口要用关键字interface

 

之前的细胞自动机,如果我们要改造成狐狸与兔子的自动机,因为动物有年龄,有动作,所以Cell的地位很尴尬如图所示

 

 因此我们可以把Cell定义为一个接口

可以让Fox和Rabbit去实现这个Cell接口,这样以后Rox和Rabbit就可以放到Cell里边去了

实现接口要用关键字implements

具体代码就不贴了,比较复杂

 

在实现接口的过程中,类用extends,接口用implements

  • 类可以实现很多接口
  • 接口可以继承接口,但不能继承类
  • 接口不能实现接口

 

 

这里就引出Java的这种面向接口的编程方式

  • 设计程序时先定义接口,再实现类
  • 任何需要在函数间传入传出的一定是接口而不是具体的类
  • 是Java成功的关键之一,因为这种方式很适合多人协作写项目,你想让同事的程序满足你的要求,只需要写一个接口就好
  • 但这个也是被Java批评的要点,因为代码膨胀起来量很快也很大

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值