1.完善多重继承
- 欲学Java,必黑C++。Java设计者原来想用C++开发一个内部项目,可是发现C++实在太烂,API不够全面,缺少垃圾回收机制,在移植的安全性和多线程上支持不够好。于是决定开发一种新的编程语言来解决这些问题,Java由此诞生。所以同学们,如果想学好Java,请跟我大喊C++是傻X。
- C++作为比较早期的面向对象编程语言,摸着石头过河,不幸的当了炮灰。比如多重继承,Java是不太欢迎继承的。因为继承耦合度太高。比如你是一个人,你想会飞,于是就继承了鸟这个类,然后你顺便拥有了一对翅膀和厚厚的羽毛,可这些玩意你并不需要。所以Java发明了接口,以契约的方式向你提供功能。想想看,你的程序里成员变量会比函数多吗?况且多重继承会遇到死亡菱形问题,就是两个父类有同样名字的函数,你继承谁的呢?其实C++也可以做到这些,那就是定义没有成员变量的纯虚类,而且所有函数都是纯虚函数。可是这些都是要靠程序员自己把握,并没有把这些功能集成到类似Interface这样的语法里。
- 所以Java只支持单重继承,想扩展功能,去实现接口吧。很快Java的设计者就发现了他们犯了矫枉过正的错误,多重继承还是有一定用处的。比如每一个人都是同时继承父亲和母亲两个类,要不然你的身体里怎么能留着父母的血呢?Java内部类应运而生。
2.实现事件驱动系统
- 用来开发GUI的Java Swing使用了大量内部类,主要用来响应各种事件。Swing的工作就是在事件就绪的时候执行事件,至于事件具体怎么做,这由事件决定。这里面有两个问题:1.事件必须要用到继承2.事件必须能访问到Swing。多说无用,上代码。
package cn.vobile;
import java.util.ArrayList;
import java.util.List;
abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start() {
eventTime = System.currentTimeMillis() + delayTime;
}
public boolean ready() {
return System.currentTimeMillis() >= eventTime;
}
public abstract void action();
}
abstract class Controller {
private List<Event> eventList = new ArrayList<Event>();
public void addEvent(Event e) {
eventList.add(e);
}
public void run() {
while (eventList.size() > 0) {
for (Event event : new ArrayList<Event>(eventList)) {
if (event.ready()) {
event.action();
eventList.remove(event);
}
}
}
}
}
class GreenHouseController extends Controller {
private boolean light = false;
public class LightOn extends Event {
public LightOn(long delayTime) {
super(delayTime);
}
@Override
public void action() {
light = true;
System.out.println("light is on");
}
}
public class LightOff extends Event {
public LightOff(long delayTime) {
super(delayTime);
}
@Override
public void action() {
light = false;
System.out.println("light is off");
}
}
}
public class Farm {
public static void main(String[] args) {
GreenHouseController ghc = new GreenHouseController();
ghc.addEvent(ghc.new LightOn(1));
ghc.addEvent(ghc.new LightOff(2000));
ghc.run();
}
}
3.闭包和回调
function Outer(){
var i=0;
function Inner(){
alert(++i);
}
return Inner;
}
var test = Outer();
- JavaScript 中闭包的产生是由于 JavaScript 中允许内部 function,也就是在一个 function 内部声明的 function 。内部 function 可以访问外部 function 中的局部变量、传入的参数和其它内部 function 。当内部 function 可以在包含它的外部 function 之外被test引用时,就形成了一个闭包。这个时候,即便外部 function 已经执行完成,该内部 function 仍然可以被执行,并且其中所用到的外部 function 的局部变量、传入的参数等仍然保留外部 function 执行结束时的值。
内部类是面向对象的闭包,因为它不仅包含创建内部类的作用域的信息,还自动拥有一个指向此外围类对象的引用,在此作用域内,内部类有权操作所有的成员,包括private成员。一般使用一个库或类时,是你主动调用人家的API,这个叫Call,有的时候这样不能满足需要,需要你注册(注入)你自己的程序(比如一个对象),然后让人家在合适的时候来调用你,这叫Callback。
public interface CallBack {
void print();
}
class Printer {
private CallBack callBack;
private String id;
public void setCallBack(CallBack callBack) {
this.callBack = callBack;
}
public void execute() {
callBack.print();
}
}
public class PrintHandler {
public static void main(String[] args) {
Printer printer = new Printer();
printer.setCallBack(new CallBack() {
@Override
public void print() {
System.out.println("print successfully");
}
});
printer.execute();
}
}
- 当父类和实现的接口出现同名函数时,你又不想父类的函数被覆盖,回调可以帮你解决这个问题。
public interface Util {
void test();
}
class Base {
public void test() {
System.out.println("base test");
}
}
public class Sub extends Base {
private class Closure implements Util {
@Override
public void test() {
System.out.println("Sub test");
}
}
public Util getUtil() {
return new Closure();
}
public static void main(String[] args) {
Sub sub = new Sub();
sub.test();
sub.getUtil().test();
}
}