第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Ruby 的元編程

如果您使用了一段時(shí)間 Ruby,那么到目前為止,您可能已經(jīng)聽到很多次“元編程”這個(gè)詞了。在元編程的章節(jié)中,我會(huì)由淺入深帶大家了解 Ruby 的元編程。

[TOC]

1. 什么是元編程

元編程是計(jì)算機(jī)程序的編寫,這些計(jì)算機(jī)程序?qū)⑵渌绦颍ɑ蛩鼈儽旧恚┳鳛閿?shù)據(jù)寫入或操作,或者在編譯時(shí)完成部分工作,而這些工作原本可以在運(yùn)行時(shí)完成。

在許多情況下,這使程序員可以在與手動(dòng)編寫所有代碼相同的時(shí)間內(nèi)完成更多工作,或者為程序提供更大的靈活性,以有效地處理新情況而無(wú)需重新編譯。

或者,更簡(jiǎn)單地說(shuō):元編程是編寫在運(yùn)行時(shí)編寫代碼的代碼,以使您的編程更輕松。

這聽上去是不是很瘋狂?

簡(jiǎn)而言之,您可以使用元編程來(lái)重新打開和修改類,捕獲不存在的方法并即時(shí)創(chuàng)建它們,通過避免重復(fù)創(chuàng)建DRY(Don’t repeat yourself)代碼等等。

Ruby常見的開源框架比如Rails、Sinatra都使用了元編程這門技術(shù)。

2. 元編程的例子

編程中的一項(xiàng)重要哲學(xué)是 DRY(不要重復(fù)自己)。多次編寫相同(或相似)的代碼不僅浪費(fèi)時(shí)間,而且在將來(lái)需要進(jìn)行更改時(shí)可能會(huì)成為一個(gè)極大的困擾。在許多情況下,可以通過編寫為您編寫代碼的代碼來(lái)消除這種重復(fù)工作。

這是一個(gè)示例:考慮一個(gè)汽車制造商的應(yīng)用程序,該應(yīng)用程序可以存儲(chǔ)和訪問每個(gè)模型的數(shù)據(jù)。在應(yīng)用程序中,我們有一個(gè)名為CarModel的類:

# Example 1
class CarModel
  def engine_info=(info)
    @engine_info = info
  end

  def engine_info
    @engine_info
  end

  def engine_price=(price)
    @engine_price = price
  end

  def engine_price
    @engine_price
  end

  def wheel_info=(info)
    @wheel_info = info
  end

  def wheel_info
    @wheel_info
  end

  def wheel_price=(price)
    @wheel_price = price
  end

  def wheel_price
    @wheel_price
  end

  def airbag_info=(info)
    @airbag_info = info
  end

  def airbag_info
    @airbag_info
  end

  def airbag_price=(price)
    @airbag_price = price
  end

  def airbag_price
    @airbag_price
  end

  def alarm_info=(info)
    @alarm_info = info
  end

  def alarm_info
    @alarm_info
  end

  def alarm_price=(price)
    @alarm_price = price
  end

  def alarm_price
    @alarm_price
  end

  def stereo_info=(info)
    @stereo_info = info
  end

  def stereo_info
    @stereo_info
  end

  def stereo_price=(price)
    @stereo_price = price
  end

  def stereo_price
    @stereo_price
  end
end

每個(gè)汽車模型都具有各種功能,例如“立體聲”,“警報(bào)”等。我們提供了一種獲取和設(shè)置汽車每個(gè)特征值的方法。每個(gè)功能都有信息和價(jià)格,因此對(duì)于我們添加到CarModel類中的每個(gè)新功能,我們需要定義兩個(gè)新方法:feature_infofeature_price。由于每種方法都相似,因此我們可以執(zhí)行以下操作來(lái)簡(jiǎn)化此代碼:

# Example 2
class CarModel
  FEATURES = ["engine", "wheel", "airbag", "alarm", "stereo"]

  FEATURES.each do |feature|
    define_method("#{feature}_info=") do |info|
      instance_variable_set("@#{feature}_info", info)
    end

    define_method("#{feature}_info") do
      instance_variable_get("@#{feature}_info")
    end

    define_method "feature_price=" do |price|
      instance_variable_set("@#{feature}_price", price)
    end

    define_method("#{feature}_price") do
      instance_variable_get("@#{feature}_price")
    end
  end
end

在此示例中,我們首先定義一個(gè)名為FEATURES的數(shù)組,其中包含我們希望為其添加方法的所有功能。

然后,對(duì)于每個(gè)功能,我們使用Ruby的Module#define_method為每個(gè)功能定義四個(gè)方法。就像示例1中一樣,四種方法是獲取功能價(jià)格和信息的getter和setter方法。唯一的區(qū)別是,它們是在定義類時(shí)動(dòng)態(tài)編寫的,而不是由我們動(dòng)態(tài)編寫的。我們使用Object#instance_variable_set()設(shè)置每個(gè)功能的實(shí)例變量的值,并使用Object#instance_variable_get返回每個(gè)功能的實(shí)例變量的值。

# Example 3
class CarModel
  attr_accessor :engine_info, :engine_price, :wheel_info, :wheel_price, :airbag_info, :airbag_price, :alarm_info, :alarm_price, :stereo_info, :stereo_price
end

定義這樣的getter和setter方法的需求在Ruby中很常見,因此Ruby已經(jīng)擁有可以做到這一點(diǎn)的方法也就不足為奇了。只需一行代碼,即可使用Module#attr_accessorattr_accessor被稱為為類宏class macro))與示例2中的功能相同。

這已經(jīng)很好了,但我們還可以更完美一點(diǎn)。

對(duì)于每個(gè)功能,我們?nèi)匀恍枰x兩個(gè)屬性(feature_info和feature_price)。

理想情況下,我們應(yīng)該能夠調(diào)用一個(gè)與示例7相同的方法,但只需列出每個(gè)功能一次即可

# Example 4
class CarModel
  # define a class macro for setting features
  def self.features(*args)
    args.each do |feature|
      attr_accessor "#{feature}_price", "#{feature}_info"
    end
  end

  # set _info and _price methods for each of these features
  features :engine, :wheel, :airbag, :alarm, :stereo
end

在此示例中,我們采用CarModel#features的每個(gè)參數(shù),并將它們傳遞給具有_price_info擴(kuò)展名的attr_accessor。

盡管這種方法比示例3中的方法稍微復(fù)雜一些,但它可以確保每個(gè)功能都被視為相同,并且意味著將來(lái)添加更多屬性將更加簡(jiǎn)單。

注意事項(xiàng):您可以使用元編程做一些非??岬氖虑?,例如用很少的代碼行添加大量功能,需要注意的是,您一定要注意代碼的可讀性,過度的元編程會(huì)使您的代碼難以理解和調(diào)試。

這看起來(lái)是不是很高大上,讓我們開始元編程的學(xué)習(xí)吧~

3. 小結(jié)

本節(jié)我們學(xué)習(xí)了什么是元編程,并用一個(gè)實(shí)例來(lái)講解了什么是元編程的概念,下節(jié)課我們正式進(jìn)入元編程的其他知識(shí)點(diǎn)學(xué)習(xí)。