<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      什么是閉包,我的理解

      首先,我覺(jué)得,一個(gè)概念,如果不理解也不影響使用的話,那么,就沒(méi)必要去理解它、去學(xué)習(xí)它。閉包就是這樣一個(gè)概念,你不理解它也能很好的用它。俺這兩年寫as3程序,是天天在和它打交道,甚至有過(guò)一個(gè)function套一個(gè),一個(gè)方法中套了20多個(gè)function的極端例子,但從未深究過(guò)它是怎么實(shí)現(xiàn)的,它就像水和空氣一樣,我們不需要知道水是H2O,空氣是氧氣氮?dú)舛趸嫉鹊幕旌衔铮不畹暮煤玫摹?/font>

      其次,我覺(jué)得,網(wǎng)上對(duì)閉包概念的解釋都太狹隘了,看得人蛋疼,就像回到了i++,++i時(shí)代一樣。如果非要去理解這個(gè)概念,像那樣去理解,則收獲太小,不值得。

      維基百科上對(duì)閉包的解釋就很經(jīng)典:

      在計(jì)算機(jī)科學(xué)中,閉包(Closure)是詞法閉包(Lexical Closure)的簡(jiǎn)稱,是引用了自由變量的函數(shù)。這個(gè)被引用的自由變量將和這個(gè)函數(shù)一同存在,即使已經(jīng)離開(kāi)了創(chuàng)造它的環(huán)境也不例外。所以,有另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。

      Peter J. Landin 在1964年將術(shù)語(yǔ)閉包定義為一種包含環(huán)境成分和控制成分的實(shí)體

      下面是我理解的閉包概念。

      先看看數(shù)學(xué)上的閉包。

      (1,5) 是一個(gè)區(qū)間,但對(duì)這個(gè)區(qū)間做分析、計(jì)算什么的,經(jīng)常會(huì)用到1和5這兩個(gè)不屬于這個(gè)區(qū)間的值,[1,5]就是(1,5)的閉包。

      在生活上,我們辦事情,找A部門,A部門說(shuō),你先得找B部門蓋個(gè)章,B部門說(shuō),你先得找C部門蓋個(gè)章,C部門說(shuō),這個(gè)東西不是我們的職權(quán)范圍…… 踢皮球,這就是非閉包。閉包就是負(fù)責(zé)到底,你找到A部門,A部門接待的那個(gè)人負(fù)責(zé)到底,他/她去協(xié)調(diào)B部門和C部門。

      在工程上,閉包就是項(xiàng)目經(jīng)理,負(fù)責(zé)調(diào)度項(xiàng)目所需要的資源。老板、客戶有什么事情,直接找項(xiàng)目經(jīng)理即可,不用再去找其它的人。

      在程序語(yǔ)言中,閉包就是一種語(yǔ)法糖,它以很自然的形式,把我們的目的和我們的目的所涉及的資源全給自動(dòng)打包在一起,以某種自然、盡量不讓人誤解的方式讓人來(lái)使用。至于其具體實(shí)現(xiàn),我個(gè)人意見(jiàn),在不影響使用的情況下,不求甚解即可。在很多情況下,需要在一段代碼里去訪問(wèn)外部的局部變量,不提供這種語(yǔ)法糖,需要寫非常多的代碼,有了閉包這個(gè)語(yǔ)法糖,就不用寫這么多代碼,自然而然的就用了。

      這樣一來(lái),可以把閉包從一個(gè)語(yǔ)法機(jī)制提升為一種設(shè)計(jì)原則

      閉包是從用戶角度考慮的一種設(shè)計(jì)概念,它基于對(duì)上下文的分析,把齷齪的事情、復(fù)雜的事情和外部環(huán)境交互的事情都自己做了,留給用戶一個(gè)很自然的接口。

      在這個(gè)原則下,函數(shù)式語(yǔ)言中,那種所謂的閉包只是一種“閉包”,還有大量的其它類型的“閉包”等待發(fā)現(xiàn)和實(shí)現(xiàn)。

      下面舉出一些閉包設(shè)計(jì)原則的正例和反例。

      正例:

      Flex中的數(shù)據(jù)綁定語(yǔ)法就是一種“閉包”。x="{b.num + c.num}",對(duì)于這個(gè)語(yǔ)法,編譯器自動(dòng)去上下文中尋找叫 b 和 c 的變量,然后再找他們內(nèi)部 num 變量,如果他們都是可綁定的話,則自動(dòng)給它們添加上綁定鏈,當(dāng) b, c, num 等有任一變動(dòng)時(shí),更新 x 的值。

      反例:

      Winform 中的設(shè)計(jì)就違反了閉包原則,當(dāng)不是在該UI線程中,更新某些控件的值時(shí),會(huì)拋出異常。只能去invoke調(diào)用,而invoke的接口很難用,相信很多人對(duì)這東東極其反感。

      閉包不一定是語(yǔ)法糖。當(dāng)我們不能直接擴(kuò)展編譯器時(shí),我們就無(wú)法增加語(yǔ)法糖來(lái)實(shí)現(xiàn)閉包機(jī)制,這時(shí),就要用現(xiàn)有的語(yǔ)言機(jī)制來(lái)實(shí)現(xiàn)了。

      下面,我們來(lái)對(duì)winform的invoke方法進(jìn)行改造,使它滿足閉包原則。下面是代碼:

          public class ControlFuncContext
          {
              public Control Control { get; private set; }
              public Delegate Delegate { get; private set; }

              public ControlFuncContext(Control ctl, Delegate d)
              {
                  this.Control = ctl;
                  this.Delegate = d;
              }

              public void Invoke0()
              {
                  if (Control.IsHandleCreated == true)
                  {
                      try
                      {
                          Delegate.DynamicInvoke();
                      }
                      catch(ObjectDisposedException ex)
                      {
                      }
                  }
              }

              public void Invoke1<T>(T obj)
              {
                  if (Control.IsHandleCreated == true)
                  {
                      try
                      {
                          Delegate.DynamicInvoke(obj);
                      }
                      catch (ObjectDisposedException ex)
                      {
                      }
                  }
              }

              public void Invoke2<T0,T1>(T0 obj0, T1 obj1)
              {
                  if (Control.IsHandleCreated == true)
                  {
                      try
                      {
                          Delegate.DynamicInvoke(obj0, obj1);
                      }
                      catch (ObjectDisposedException ex)
                      {
                      }
                  }
              }
          }

          public static class FormClassHelper
          {

              public static void InvokeAction(this Control ctl, Action action)
              {
                  if (ctl.IsHandleCreated == true)
                  {
                      ControlFuncContext fc = new ControlFuncContext(ctl, action);
                      ctl.Invoke(new Action(fc.Invoke0));
                  }
              }

              public static void InvokeAction<T>(this Control ctl, Action<T> action, T obj)
              {
                  if (ctl.IsHandleCreated == true)
                  {
                      ControlFuncContext fc = new ControlFuncContext(ctl, action);
                      ctl.Invoke(new Action<T>(fc.Invoke1<T>), obj);
                  }
              }

              public static void InvokeAction<T0, T1>(this Control ctl, Action<T0, T1> action, T0 obj0, T1 obj1)
              {
                  if (ctl.IsHandleCreated == true)
                  {
                      ControlFuncContext fc = new ControlFuncContext(ctl, action);
                      ctl.Invoke(new Action<T0, T1>(fc.Invoke2<T0, T1>), obj0, obj1);
                  }
              }
          }

      使用起來(lái)很簡(jiǎn)單,直接調(diào)用擴(kuò)展方法 InvokeAction 即可,不必去考慮跨線程還是不跨線程這些“環(huán)境因素”,跨線程調(diào)用,我們已經(jīng)通過(guò)用戶不必知曉的方式,把它封裝起來(lái)了。

      再舉個(gè)例子,寫程序經(jīng)常需要這樣一個(gè)功能:打開(kāi)一個(gè)圖像文件,然后進(jìn)行處理。正常寫法很麻煩,比如,那個(gè)filter格式就很容易忘記,那么,我們就把它閉包化,把不該讓用戶知道,不該讓用戶敲鍵盤的都給它封裝起來(lái):

      public static void OpenFile(this Form element, Action<String> callbackOnFilePath, String filter = "所有文件|*.*")

              {

                  String filePath;

                  OpenFileDialog dlg = new OpenFileDialog();

                  dlg.Filter = filter;

                  dlg.FileOk += (object sender, CancelEventArgs e) =>

                  {

                      filePath = dlg.FileName;

      if (callbackOnFilePath != null)

                          callbackOnFilePath(filePath);

                  };

                  dlg.ShowDialog();

              }

      public static void OpenImageFile(this Form element, Action<String> callbackOnFilePath, String filter = "圖像文件|*.bmp;*.jpg;*.gif;*.png")

              {

                  OpenFile(element, callbackOnFilePath, filter);

              }

      再舉一個(gè)例子,這個(gè)例子是as3中的。在Flex中,控件有一個(gè)callLater 方法,在下一幀時(shí)進(jìn)行調(diào)用。這個(gè)方法非常有用,很多時(shí)候,非Flex項(xiàng)目也需要這樣的一個(gè)方法。下面,我們進(jìn)行模擬:

      package orc.utils
      {
          import flash.display.Stage;
          import flash.events.Event;

          public class CallLaterHelper
          {
              public function CallLaterHelper(stage:Stage, callback:Function)
              {
                  this.callback = callback;
                  this.stage = stage;

                  stage.addEventListener(Event.ENTER_FRAME, onStageEnterFrame);
              }
              private var stage:Stage;
              private var callback:Function;
              private function onStageEnterFrame(event:Event):void
              {
                  stage.removeEventListener(Event.ENTER_FRAME, onStageEnterFrame);
                  if(callback != null)
                  {
                      callback();
                  }
              }
          }
      }

      然后在基礎(chǔ)控件中,提供callLater方法:

      public function callLater(callback:Function):void
      {
          new CallLaterHelper(this.stage,callback);
      }

      總結(jié):

      (1)閉包是一種設(shè)計(jì)原則,它通過(guò)分析上下文,來(lái)簡(jiǎn)化用戶的調(diào)用,讓用戶在不知曉的情況下,達(dá)到他的目的;

      (2)網(wǎng)上主流的對(duì)閉包剖析的文章實(shí)際上是和閉包原則反向而馳的,如果需要知道閉包細(xì)節(jié)才能用好的話,這個(gè)閉包是設(shè)計(jì)失敗的;

      (3)盡量少學(xué)習(xí)。

      posted @ 2011-08-03 14:18  xiaotie  閱讀(46897)  評(píng)論(40)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产午夜亚洲精品久久| 亚洲日韩精品无码一区二区三区| 亚洲综合另类小说色区色噜噜| 午夜AAAAA级岛国福利在线 | 青青草久热这里只有精品| 免费99精品国产人妻自在现线| 玉林市| 国产一二三五区不在卡| 欧美和黑人xxxx猛交视频| 一本色道久久综合亚洲精品| 日韩a∨精品日韩在线观看| 国产台湾黄色av一区二区| 亚洲av片在线免费观看| 国产二区三区不卡免费| 国产av成人精品播放| 亚洲中文字幕精品久久久久久动漫 | 国产av永久无码天堂影院| 亚洲精品中文综合第一页| 亚洲精品日韩在线丰满| 国产精品久久久久鬼色| 亚洲国产精品日韩AV专区| 成人精品一区二区三区四| 日本污视频在线观看| 超碰成人人人做人人爽| 国产成人精品亚洲精品日日| 亚洲老熟女一区二区三区 | 国产成人精品一区二区三区| 精品一区二区三区不卡| 国产成人人综合亚洲欧美丁香花 | 国产丰满乱子伦无码专区| 中国少妇人妻xxxxx| 国产小嫩模无套中出视频| 国产午夜影视大全免费观看| 亚洲欧美综合精品成人网站| 国产精品亚洲一区二区三区| 被拉到野外强要好爽| 欧洲精品码一区二区三区| 九九热视频在线播放| 亚洲人成人网站色www| 色悠悠国产在线视频一线| 不卡国产一区二区三区|