对于开发语言闭包实现的理解

本文详细解释了闭包这一编程模式在不同语言中的实现方式及其意义。通过JavaScript和Java的具体示例,阐述了闭包如何帮助隐藏内部逻辑,保护数据完整性和有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

闭包不是某些编程语言的专属,它是一种编程模式。

不同的语言对闭包的支持和实现方式是不一样的,例如Groovy和JavaScript等动态语言可以实现方法级别的闭包,像java这样的语言只能从类级别开始实现。

先来看各种闭包如何实现:

javascript:

这段脚本里面,say函数中定义了con和end引用的匿名函数,这么做就称为闭包,其实意图很明显,只希望con和匿名函数在say函数中可见,对外部隐藏,当使用它们的时候,只需要把say()函数传递给调用者havefun()即可。形象的说,将其据为己有,画地为牢,打造自己内部的层次和结构,外部根本不知道其内部实现,这就是闭包的意义。在闭包里面的变量等结构仍然遵循作用域规则,如nick对于con()是全局变量等等,这些都和平常一样,不要认为是闭包的什么特点。

<script>
	var fun = function say(){
		var name = document.getElementById("n");
		var nick = "dear";
		con();
	
		function con(){
			alert(nick+name.innerHTML);
		}
		
		var end = function(arg){
		nick = nick+arg;
		alert(nick);
		}("beauty")
	}
	
	function havefun(func){
		func();
		}
	
</script>
</head>
<body>
<p id="n" onclick="havefun(fun)">妹子</p>

groovy的闭包:http://blog.youkuaiyun.com/shewmi/article/details/78820031

对于闭包,网上很多人说法不一,总结如下几点:

1、有人说闭包是语法糖,函数式编程

2、有人说闭包是只处理唯一的任务

3、有人说闭包是用来共享函数局部变量

4、有人说闭包为了避免垃圾回收

5、有人说闭包是函数中定义函数

6、还有人说闭包是为了让外部访问内部的东西

我认为,这些说法都有其道理,但是都不准确,也不全面,比较狭隘。从上面的例子我已经说了闭包的意义是什么。但是在一些动态语言中,大多数是函数式编程,函数的粒度和级别太小,闭包的特性不是那么明显。我们来看一下高级特性:

java:

我们先定义一个Computer类,其中name、ram、kbs三个属性被设定为私有(外部不可见),另外方法设定为protected(仅同包的和其子类可见),那么这就是对computer的一个简单的封装,其实想想,闭包的思想和封装殊途同归,只是层次不一样,封装是面对各种类型的,如属性,方法,内部类等,而闭包则是封装的一个个体或每一道工序。在这个java类中,它的属性和方法就是进行了不同程度的闭包处理:

我们在另一个包中编写一个测试类,首先创建一个computer对象,然后调用其方法或属性,发现编译不能通过,这就是因为其属性和方法被闭包处理了,所以外部不能随意的直接操作computer的属性和方法:

那么在java中,使用匿名内部类可以让闭包的东西上升一个层次,所谓匿名内部类,其实就是这个computer类的子类,由于不需要类名所以称为匿名,并且因为它是子类,所以可以使用computer中闭包的属性和方法,来看:

输出:

也正因如此,有很多人认为闭包就是借用某个类的方法,这是不正确的,也并不是通过匿名内部类就可以打破这个约束,其实,上面的操作仍然是一个闭包。再来看:

上面的操作中,我们尝试在语句中抛出异常,然而编译不通过,因为匿名内部类中执行的代码块是对象实例初始化代码,在对象创建过程中出现异常,那么对象就不能正常创建,因此这是一个原子操作,要么成功,要么失败。你可能想到一点,虽然初始化代码块没有正常结束,但是new Computer()方法是调用了构造方法,这个应该会执行成功。的确,如上所述,对象仍然会被创建,如果这个异常不是抛出而是被捕获会怎样?

我们修改一下computer的方法,模拟中毒,所以我们也准备类另一个方法repair,用来杀毒:

显然,如果这个闭包的对象在初始化过程中出现了错误,那么它将报废,你只能重新创建computer对象并重新初始化它,也就是说,这个对象com是一次性的,一旦创建,只要离开了匿名内部类,你甭想在操作它或者修改,也不用担心别的地方会擅自修改或操作它,除非重新创建,但是它原来的数据别人已经拿不到了,这样一来就保证了数据内容的完整性和有效性。

再来看,想利用repair来杀毒也只能在内部类中来执行,或者由专业人士处理(同包的类或子类),这样也就相当于computer内部的操作。如:

到这里,闭包的作用应该清楚了,闭包在函数层面来说就是隐藏内部调用逻辑,允许内部进行结构化编写但不被外部所用。在面向对象的概念上来讲,其作用就是隐藏对象内部内容,防止外部进行直接操作,在一定程度上保证数据的完整和有效。闭包是封装的一个特写。但是正如责任链模式那样,闭包的东西总得有个开口跟外界交互,否则数据就是去了意义,但是内部的定义又不能被外部直接访问,看似矛盾,其实这正是迪米特法则(最少知道原则)的体现,闭包的内部都应当是服务于自身,而对外部是无须利用的,这种前提下才考虑使用闭包。如果内部逻辑是外部可以复用的,则应将其当分离解耦。

最后提一下,上面的例子中,并不是完全闭包,因为computer要跟外界交互,我们只需要适当的封装,然后公开一些入口给外部调用即可,因此封装要适度,过度的封装会影响代码结构和实现能力,所以完全的闭包一般是不会有的,如果我们将computer的类修改为final,那么他就不能被继承从而防止闭包被打破,闭包性进一步加强,而这样使用匿名内部类途径交互变为不可能,通常情况下,我们只需要在同包创建一个类来代理使用computer即可。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值