1.接口
定义:接口是一个纯抽象类,其中所有的成员变量都是public static final(不属于任何对象,属于类,且不会被改变,是常量)。 接口是一种规范,规定了长什么样,但是不管里面有什么,接口需要被实现,实现了接口的类的对象可以被认识该接口的类所处理。
打个比方,Field这个类只认识Cell类,Rabbit类和Fox类都继承自Animal类,但是要将Rabbit和Fox放入Field处理,则可以将Cell类变成一个接口,由Rabbit和Fox去实现。
public interface Cell {//注意这里不能写成interface class
/**
* *Cell是一个接口而非类(接口是一种完全抽象的抽象类,interface是一种特殊的Class,和Class地位一样)
* 这个接口就是为了实现Fox和Rabbit类new的对象能够传递给Field类
* Field类中指明需要的对象的类是Cell而Cell是作为中间承接者
* Fox和Rabbit类需要有implements Cell语句来实现接口
*/
/**
* !注意这里函数可以不用写函数前缀,只需要写返回值类型
* ?抽象类无函数主体,只需声明函数原型,实现抽象类/接口的类都必须Override所有抽象方法,否则此子类仍为抽象类
* ?abstract与final是冲突对立关系,抽象是用来被继承或重写的,final相反是不让继承/重写的
*/
//Fox和Rabbit实现了Cell后,必须去Override这个draw
void draw(Graphics g, int x, int y, int size);
}
Cell里只定义了一个抽象函数draw,Fox和Rabbit实现了Cell后,必须去Override这个draw。
这里给出Fox实现Cell的过程:
public class Fox extends Animal implements Cell {
//这里是构造函数,继承了Animal里的数据
public Fox() {
super(20, 4);
}
@Override // 实现接口Cell中的draw()
public void draw(Graphics g, int x, int y, int size) {
int alpha = (int) ((1 - getAgePercent()) * 255);
g.setColor(new Color(0, 0, 0, alpha));
g.fillRect(x, y, size, size);
}
}
然后,Fox和Rabbit的对象都能被放到Field里面去。
2.内部类
顾名思义,内部类是定义在别的类内部、函数内部的类,也是成员,可以访问外部的全部资源。(包括任何私有成员,如成员函数、成员变量),当外部是函数时,去访问函数的本地变量时,那个变量必须是final类型才可以被内部类访问。
3.匿名类
给出一段代码:
该方法定义在一个构造函数里。
btnStep.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//TODO Auto-generated method stub
System.out.println("按下啦!");
step();
frame.repaint();
}
});
btnStep是定义的一个JButton对象,是个按钮。ActionListener是个Java里Swing消息机制里的接口。Swing消息机制里,每一个部件发出的消息,需要有一个新的类去实现一个新的方法,然后去接收那个消息。当程序里有很多按钮、很多控件时,如果没有匿名类的存在,每一个新方法都需要被起名字。起名字很麻烦。
ActionListener()后面的一对大括号里做的事情,是定义了一个新的类,这个类实现了ActionListener接口。
在new对象的时候给出的类的定义形成匿名类,匿名类可以继承某类,也可以实现某接口。
又由于该类又被定义在一个函数里,所以属于内部匿名类。
Swing的消息机制广泛使用匿名类。