作者:
0009
看这么一个实例:
计算两个数字,返回一个结果,计算方法未知,可以是相加,相减,相乘,相除等等.
该模型就是: Compute(x, y, ComputeMethod)
Compute方法需要三个参数, x, y两个数字,和一个执行计算的方法ComputeMethod.
用了解决此类问题,于是,C++中有了函数指针,C#中有了委托,而做为支持函数式编程的JavaScript更为彻底,函数(方法)的本质上就是一个变量,变量能怎么传,他就能怎么传.
注: JavaScript是目前计算机语言中极少数能支持函数式编程的语言之一, 函数式编程!=面向函数编程,是一种比面向对象更为抽象,更为接近数学本质的编程方法.以后我会给你讲这方面内容.
C++我就不讲了,我们先看一下这个问题用C#是怎么解决的.
因为C#是强类型的,你必须规定好了ComputeMethod的内容,比如有没有返回值,有几个参数,他才让你传递,因此C#的设计者就必须想出一个安全合理的解决方案.
┏━━━━━━━━━━━━━━━━━━┓
┃Add, Subtract, Multiply, Divide ....┃
┗━━━━━━━━━━━━━━━━━━┛
│
│ ┏━━━━━━━━━━━━━━┓
↓─┃通过一个中间载体,即delegate┃
│ ┗━━━━━━━━━━━━━━┛
↓
┏━━━━━━━┓ ┏━━━━━━━━━━━━━━┓
┃ComputeMethod ┃→┃Compute(x, y, ComputeMethod)┃
┗━━━━━━━┛ ┗━━━━━━━━━━━━━━┛
首先我们声明一个中间载体:delegate int ComputeMethod(int x, int y);
这个委托有什么含义呢?
1.委托本质上是一个类,一个特殊的类,这个类继承于System.MulticastDelegate,其特殊行为你可以以后再深入研究,你只要用类的标准来看待delegate就行了.
2.这个委托规定好了"ComputeMethod"的内容:接受两个int参数,并返回一个int.
好,有了这个委托我们就可以写Compute方法了:
int Compute(int x, int y, ComputeMethod method)
{
// return method.Invoke(x, y);
return method(x, y);
}
说明:
method(x, y)实质上隐式调用method.Invoke(x, y),当然你可以显式调用method.Invoke(x, y).这样更接近事物的本质,因为"执行委托"的本质是"执行别人委托给他的方法".
我们再来写几个实现:
int Add(int x, int y)
{
return x + y;
}
int Subtract(int x, int y)
{
return x - y;
}
int Multiply(int x, int y)
{
return x * y;
}
int Divide(int x, int y)
{
return x / y;
}
完整的例子
class Program
{
delegate int ComputeMethod(int x, int y);
static void Main()
{
int x = 9, y = 3;
ComputeMethod add = new ComputeMethod(Add);
ComputeMethod subtract = new ComputeMethod(Subtract);
ComputeMethod multiply = new ComputeMethod(Multiply);
ComputeMethod divide = new ComputeMethod(Divide);
Console.WriteLine(ActCompute(x, y, add));
Console.WriteLine(ActCompute(x, y, subtract));
Console.WriteLine(ActCompute(x, y, multiply));
Console.WriteLine(ActCompute(x, y, divide));
}
static string ActCompute(int x, int y, ComputeMethod method)
{
if (method != null)
{
// method.Invoke(x, y);
return String.Format("{0}({1}, {2}) = {3}", method.Method.Name, x, y, method(x, y));
}
else
{
throw new Exception("Compute Method is null!");
}
}
static int Add(int x, int y)
{
return x + y;
}
static int Subtract(int x, int y)
{
return x - y;
}
static int Multiply(int x, int y)
{
return x * y;
}
static int Divide(int x, int y)
{
return x / y;
}
}
查了一下资料,.net2.0中已经支持匿名方法和隐式声明delegate,这两种方式和javascript中的使用方法相似,我写了个例子你参考一下.
class Program
{
delegate int ComputeMethod(int x, int y);
static void Main()
{
int x = 9, y = 3;
//ComputeMethod add = new ComputeMethod(Add);
ComputeMethod subtract = new ComputeMethod(Subtract);
ComputeMethod multiply = new ComputeMethod(Multiply);
//ComputeMethod divide = new ComputeMethod(Divide);
Console.WriteLine(ActCompute(x, y, Add)); // 直接调用Program.Add,实际上是隐式声明delegate
Console.WriteLine(ActCompute(x, y, subtract));
Console.WriteLine(ActCompute(x, y, multiply));
Console.WriteLine(ActCompute(x, y, delegate(int x2, int y2) { return x2 / y2; })); // 匿名方法
}
static string ActCompute(int x, int y, ComputeMethod method)
{
if (method != null)
{
// method.Invoke(x, y);
return String.Format("{0}({1}, {2}) = {3}", method.Method.Name, x, y, method(x, y));
}
else
{
throw new Exception("Compute Method is null!");
}
}
static int Add(int x, int y)
{
return x + y;
}
static int Subtract(int x, int y)
{
return x - y;
}
static int Multiply(int x, int y)
{
return x * y;
}
//static int Divide(int x, int y)
//{
// return x / y;
//}
}
我们看用支持函数式编程的JavaScript是怎么样来解决这个问题的:
首先,写Compute函数:
function Compute(x, y, fun)
{
return fun(x, y);
}
相信这个表达已经相当清晰我不需要再做解释了,在JavaScript中函数也是一种变量,而且JS不是类型安全的语言,所以直接传递就行.
写一个实现来试试
function Add(x, y)
{
return x + y;
}
function Compute(x, y, fun)
{
return fun(x, y);
}
alert(Compute(9, 3, Add));
C#就像刀法,招式严整,深厚有力;而JavaScript更像剑法,灵活轻巧,一剑穿心.
你看看这个问题JS的各种写法:
function Add(x, y) // 常规方法
{
return x + y;
}
var Subtract = function (x, y) // 在面向对象开发时经常用到
{
return x - y;
}
var Multiply = new Function("x", "y", "return x * y;"); // 实现function的原始方式,但是不推荐,效率很低.
function Compute(x, y, fun)
{
return fun(x, y);
}
alert(Compute(9, 3, Add));
alert(Compute(9, 3, Subtract));
alert(Compute(9, 3, Multiply));
alert(Compute(9, 3, function (x, y){ return x / y; })); // 轻便型的实现方法,小函数时用可用.
第四种方法举例:
<span id="s"></span>
<script language="JavaScript">
setInterval(function (){document.getElementById("s").innerHTML=Date();}, 1000);
</script>
转载于:https://www.cnblogs.com/guodapeng/archive/2007/11/13/958320.html