亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 17415 | 回復(fù): 2
打印 上一主題 下一主題

嘎嘎叫的小狗——快樂的鴨子類型 [復(fù)制鏈接]

論壇徽章:
2
2015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:55:28
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2013-08-23 09:32 |只看該作者 |倒序瀏覽
  

  
鴨子類型是我目前在Ruby語言里最喜歡的一個“功能特征”,主要是因為它能讓我們輕松的寫出漂亮的代碼——畢竟,你無需再擔(dān)心類型:你可以把精力全部集中到你想發(fā)送的消息上,以及你需要打交道的對象能發(fā)揮的功能上。

我第一次接觸Ruby時就知道它是一種“鴨子類型語言”,但我的靜態(tài)編譯型語言的背景知識妨礙了我真正理解鴨子類型的真正含義。理論很簡單:如果你設(shè)計一個方法,它需要一個‘鴨子’參數(shù),那么你呼叫一聲“嘎嘎”,任何以“嘎嘎”回應(yīng)你的對象都可以傳入這個方法——這個對象究竟是什么類型并不重要。很顯然,你可以得出這樣的結(jié)論,如果你寫出一個Dog類,它實現(xiàn)了一個叫“嘎嘎”的方法(很奇怪的狗),那么,你可以把這個狗傳入上面的那個方法,一點問題都沒有。非?岚桑喿宇愋偷膹(qiáng)大功能震撼了我,我認(rèn)識到,它在各種對象間打通了一條重要的溝通途徑,強(qiáng)化了API的能力,減少了代碼中的干擾。為了說明這些,讓我來展示一些Ruby標(biāo)準(zhǔn)庫中的幾個例子。
File.open
File.open(“path/to/file&rdquo最常見的讀取文件的方法:你傳入path,這個方法會返回一個能讀取文件的對象。你是否注意到,我加粗強(qiáng)調(diào)了“path”這個詞。這是特意的——這個‘open’函數(shù)實際可以接受任何可以扮演路徑角色的東西,并不僅僅指路徑字符串。這區(qū)別有些微妙,但你會發(fā)現(xiàn)我們可以把代碼這樣寫:

class VimConfig
  # ... behavior ... #        
  def to_path
    "~/.vimrc"
  end
end
config = VimConfig.new
config_file = File.open config
   很帥,不是嗎?Ruby的File API在使用它的參數(shù)前會進(jìn)行轉(zhuǎn)化,轉(zhuǎn)化的一種途徑是通過‘to_path’方法。如果你感到奇怪,下面是實現(xiàn)它的C語言代碼(‘rb_f_open’ 調(diào)用 ‘FilePathValue’,后者最終調(diào)用 ‘rb_get_path_check_to_string&rsquo):

static VALUE
rb_f_open(int argc, VALUE *argv)
{
    ID to_open = 0;
    int redirect = FALSE;
    if (argc >= 1) {
  CONST_ID(to_open, "to_open";
        if (rb_respond_to(argv[0], to_open)) {
            redirect = TRUE;
        }
        else {
            VALUE tmp = argv[0];
            FilePathValue(tmp);
            if (NIL_P(tmp)) {
                redirect = TRUE;
            }
            else {
                VALUE cmd = check_pipe_command(tmp);
                if (!NIL_P(cmd)) {
                    argv[0] = cmd;
                    return rb_io_s_popen(argc, argv, rb_cIO);
                }
            }
        }
    }
    if (redirect) {
        VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
        if (rb_block_given_p()) {
            return rb_ensure(rb_yield, io, io_close, io);
        }
        return io;
    }
    return rb_io_s_open(argc, argv, rb_cFile);
}
VALUE
rb_get_path_check_to_string(VALUE obj, int level)
{
    VALUE tmp;
    ID to_path;
    if (insecure_obj_p(obj, level)) {
        rb_insecure_operation();
    }
    if (RB_TYPE_P(obj, T_STRING)) {
        return obj;
    }
    CONST_ID(to_path, "to_path";
    //to_path call!
    tmp = rb_check_funcall(obj, to_path, 0, 0);
    if (tmp == Qundef) {
        tmp = obj;
    }
    StringValue(tmp);
    return tmp;
}
數(shù)組索引
數(shù)組索引(a_array[index])是另外一個很好的例子:它會向索引調(diào)用‘to_int’方法,所以,任何能響應(yīng)to_int方法的對象都可以當(dāng)作索引。這讓我們可以這樣寫:
class PodiumPosition
  # .. behavior .. #
  def to_int
    @race_position
  end
end
position = PodiumPosition.new(1)
prizes = [ "orange", "apple", "corn" ]
puts "Congrats, you won #{prizes[position]}"
IO.select
我是通過IO.select API才第一次發(fā)現(xiàn)了Ruby的強(qiáng)大。這個API會調(diào)用系統(tǒng)select(2)函數(shù),接收文件描述符參數(shù),并掛起當(dāng)前的線程,直到有文件可以進(jìn)行讀寫操作。這個Ruby函數(shù)定義如下:
select(read_array
        [, write_array
        [, error_array
        [, timeout]]]) → array or nil
因此,你可以傳入一個數(shù)據(jù)流數(shù)組,而“select”函數(shù)會一直等到流文件準(zhǔn)備好可讀或可寫。問題是,很多數(shù)據(jù)流是存儲在具有各種行為特征的特定對象里的(例如一個執(zhí)行網(wǎng)絡(luò)操作的Connection類),這些對象里的IO接口通常經(jīng)過了二次封裝,外界無法直接訪問。根本不可能通過重構(gòu)內(nèi)核代碼來適應(yīng)‘select’ API。打破它的封裝嗎?很顯然不行!這時‘to_io’方法就成了救星!
class Connection
  # .. rest of the class .. #
  def accept_connection(io)
    @io = io
    # new connection code
  end
  def to_io
    @io
  end
end
class Reactor
  # array_of_connections_to_read is an array of instances of the above Connection class
  # array_of_connections_to_write is an array of instances of the above Connection class
  def tick
    to_read, to_write = IO.select(array_of_connections_to_read, array_of_connections_to_write)
  end
end
你可以看到,Ruby的標(biāo)準(zhǔn)庫里到處都是鴨子類型

.
重構(gòu)
最明顯,也是最值得一提的鴨子類型的好處是,它讓重構(gòu)變得更容易:“用多型替換條件判斷”和 “Replace Type Code with Strategy/State”的重構(gòu)原則,當(dāng)你不需要考慮類型、只關(guān)心行為時,這些都變得極其簡單和容易實現(xiàn)。

鴨子類型的黑暗面
沒有編譯器為你探路是很危險的。專業(yè)的Ruby程序員(1)永遠(yuǎn)不會忘記有責(zé)任測試它們的代碼的各種行為,并且(2)一定寫出整潔的代碼,并及時重構(gòu)。Ruby代碼必須要認(rèn)真寫,否者調(diào)試起來就會是一場噩夢。

同時,動態(tài)語言一般最合適的是開發(fā)小型或中型軟件。我的經(jīng)驗告訴我,當(dāng)系統(tǒng)變得復(fù)雜時,最好把它拆分成小的應(yīng)用,如果是用動態(tài)語言開發(fā)的,那這種做法更加重要——一個reddit的網(wǎng)友說需要在一個10萬行的程序了修改一個函數(shù)的名稱,我只能說,這很難實現(xiàn)。修改公開的接口,這很難很難。有時最好把它標(biāo)注為‘廢棄’就行了。

結(jié)論
動態(tài)語言能漂亮的解決你的問題,但需要有很好的設(shè)計,Ruby的標(biāo)準(zhǔn)庫里鴨子類型為我們提供了方便的途徑。它是一個很好的例子,向我們展示了一個Ruby程序員該如何的編程:按對象的行為——而不是按對象的類型——來接收參數(shù)。

我希望這篇文章給那些仍然不明白像Ruby這樣的語言的強(qiáng)大之處的人帶來新的認(rèn)識。我推薦閱讀下面幾本書來進(jìn)一步的學(xué)習(xí):

[英文原文:Quacking The Dog - Duck typing for happiness]

轉(zhuǎn)自:http://www.aqee.net/quacking-the-dog-duck-typing-for-happiness/


本文來自ChinaUnix新聞頻道,如果查看原文請點:http://news.chinaunix.net/opensource/2013/0823/2907892.shtml

論壇徽章:
7
戌狗
日期:2013-12-15 20:43:38技術(shù)圖書徽章
日期:2014-03-05 01:33:12技術(shù)圖書徽章
日期:2014-03-15 20:31:17未羊
日期:2014-03-25 23:48:20丑牛
日期:2014-04-07 22:37:44巳蛇
日期:2014-04-11 21:58:0915-16賽季CBA聯(lián)賽之青島
日期:2016-03-17 20:36:13
2 [報告]
發(fā)表于 2013-08-29 04:23 |只看該作者
這就非常酷了。。

論壇徽章:
0
3 [報告]
發(fā)表于 2013-10-05 13:51 |只看該作者
這鴨子類型
有些微妙
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP