Thinking in java 读书笔记(七.2:内部类:闭包和控制框架)

一、
内部类是就是面向对象的一种闭包形式。
首先说说闭包。最坑爹的闭包应该是JavaScript的闭包了,JS函数外部无法读取函数内的变量,而函数内可以读取外部变量,然后当外部需要读取内部变量时就需要使用闭包(JS一般使用一个function表示闭包)。
而对于Java来说,可以吧函数类比为class,当我们需要读取某个class的某个private的参数可以使用内部类来访问,因为内部类可以透明的访问它所嵌入的外围类的所有成员。
书上例子如下

package com.company.ChildrenClass;
interface Incrementable{
    void increment();
}
class Callee1 implements Incrementable{
    private int i = 0;
    @Override
    public void increment() {
        i++;
        System.out.println(i);
    }
}

class MyIncrement{
    public void increment(){
        System.out.println("other operation");
    }
     static void f(MyIncrement myIncrement){
        myIncrement.increment();
    }
}
class Callee2 extends MyIncrement{
    private int i=0;
    public void increment(){
        super.increment();
        i++;
        System.out.println(i);
    }
    private class Closure implements Incrementable{
        @Override
        public void increment() {
            Callee2.this.increment();
        }
    }
    Incrementable getCallBackReference(){
        return new Closure();
    }
}

class Caller{
    private Incrementable callbackReference;
    Caller(Incrementable callbackReference){
        this.callbackReference = callbackReference;
    }
    void go(){
        callbackReference.increment();
    }
}
/*这里的回调似乎是为了动态扩展
* Callee2由于继承的父类已经存在接口中的方法,想要同时实现父类和接口的方法,
* 需要的就是内部类(其实已经是多继承的一种实现吧),内部类来实现接口,然后提供回调,传出内部类引用
* */
public class CallBacks {
    public static void main(String[] args) {
        Callee1 callee1 = new Callee1();
        Callee2 callee2 = new Callee2();
        MyIncrement.f(callee2);
        Caller caller1 = new Caller(callee1);
        Caller caller2 = new Caller(callee2.getCallBackReference());
        caller1.go();
        caller2.go();
    }
}

二、控制框架
这里引入了第三种设计模式:模板方法。事实上其实应用框架是模板方法的一种实现,而控制框架是一种特殊的应用框架。
应用框架是设计来解决某种特定问题的一组类。运用某个应用程序框架,通常是继承一个或者多个类并且覆盖某些方法,在覆盖的方法中编写解决方案。
有写过JavaFX和Android,这两个应该都是这种应用框架的实现。但是书上用的swing举例。所以这里算是应用框架初探了…。

模板方法最关键的地方是使变量和常量分离

//书中以下示例代码将忽略具体的event细节而设计框架。
public abstract class Event {
    private long eventTime;
    protected final long delayTime;
    public Event(long delayTime){
        this.delayTime = delayTime;

    }
    public void start(){
        //allows restarting
        eventTime = System.nanoTime()+delayTime;//generate start time;
    }
    public boolean ready(){
        return System.nanoTime()>=eventTime;
    }
    public abstract void action();
}



public class Controller {
    private List<Event> eventList = new ArrayList<>();
    public void addEvent(Event event){
        eventList.add(event);
    }
    public void run(){
        while (eventList.size()>0){
            //不是很清楚为什么要用副本
            for (Event e:new ArrayList<Event>(eventList)){
                if (e.ready()){
                    System.out.println(e);
                    e.action();
                    eventList.remove(e);
                }
            }
        }
    }
}

然后内部类和控制框架有什么关心呢,内部类一般用来改写event(至少目前只碰到过这个)。虽然现在自己个人写点东西都喜欢使用lambda表达式,或者直接使用匿名内部类,但是事实上使用内部类来写event可读性高的不是一点两点,还是改城用内部类吧。

//这里不使用书上的实例代码,放个写javafx的实例
//设置JavaFXStage关闭时的动作。
primaryStage.setOnCloseRequest(new WindowsCloseEvent(primaryStage));

class WindowsCloseEvent implements EventHandler<WindowEvent> {

        private Stage stage;

        public WindowsCloseEvent(Stage stage){
            this.stage = stage;
        }

        public void handle(WindowEvent event) {
            event.consume();
            if (!isSendFile&&!isRecFile){
                UserBean clientBean = new UserBean();
                clientBean.setType(-1);
                clientBean.setName(username);
                clientBean.setTimer(DateUtil.getTimer());
                sendMessage(clientBean);
                primaryStage.close();

            }
            if (isRecFile){
                dialogController.setText("正在接受文件无法退出");
                Dialog.show();
            }
            if (isSendFile){
                dialogController.setText("正在发送文件无法退出");
                Dialog.show();
            }
        }
    }

三、内部类的继承、覆盖

public class InheritInner extends WithClass.Inner {
//因为非static的内部类如果外部类没有初始化的话,内部类也就不存在的,
//所以需要传入一个外部类的实例
    InheritInner(WithClass withClass){
        withClass.super();
    }
    public static void main(String[] args) {
        WithClass wi = new WithClass();
    }
}
class WithClass{
    class Inner{}
}
//因为内部类的访问需要通过外部类,所以其实子类是无法覆盖父类的内部类的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值