您的位置:首页 > 编程语言 > Java开发

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

2018-02-12 20:47 375 查看
一、

内部类是就是面向对象的一种闭包形式。

首先说说闭包。最坑爹的闭包应该是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{}
}
//因为内部类的访问需要通过外部类,所以其实子类是无法覆盖父类的内部类的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: