2011-08-18 47 views
1

我一直在嘗試通過閱讀其他人的代碼在ruby中獲得元編程的竅門。我有這段代碼對我來說可能太難以調試了。這是代碼。添加到元類中的Ruby對象是不可見的

#!/usr/bin/env ruby 

class Person 

    def print_name 
    p "#{Person.identity.name}" 
    end 

    class << self 
    attr_accessor :identity 

    def identify() 
     self.identity ||= Identity.new 
     yield(identity) 
    end 
    end 

    class Identity 
    attr_accessor :name 

    def initialize 
     @name = "kibet" 
    end 
    end 
end 

me = Person.new 
me.print_name 

而我得到的錯誤是這樣的

`print_name': undefined method `name' for nil:NilClass (NoMethodError) 
    from ./meta_config.rb:28 

幫助的高度讚賞。

+0

如果你解釋了你的目標是什麼,你的代碼有問題,但看起來你正在使用錯誤的工具來做這件事情會更簡單。 –

+0

錯誤是因爲'@ identity'在調用'print_name'時尚未初始化。也就是說,'identify'沒有被調用(並且你必須擺脫那個「yield」)。 –

+0

@santos謝謝你的想法。老實說,我濫用了這段代碼中的一些ruby特性。 –

回答

2

我隱約明白了,你試圖做有..看看這個

class Person 

    def print_name 
    p "#{Person.identity.name}" 
    end 

    class << self 
    attr_accessor :identity 

    def identity 
     @identity || Identity.new 
    end 
    end 

    class Identity 
    attr_accessor :name 

    def initialize 
     @name = "kibet" 
    end 
    end 
end 

me = Person.new 
me.print_name 

注意事項:

  • 我猜的方法名是一個錯字。你的意思是識別身份,請擺脫大括號。這是紅寶石:)
  • 調用self.identity裏面會導致一個stackoverflow。因此,直接訪問實例變量的值
  • 我還是不明白爲什麼你需要一個產量,當你永遠不會通過一個塊。
+0

哈哈!我來自java背景,所以我可能會在一些地方放置一些大括號,但我試圖克制自己。但是,謝謝你提到一些亮點,我想我需要更多的閱讀和練習一些ruby的特性。 –

0

我發現了兩個問題:

def print_name 
    p "#{Person.identify.name}" 
end 

有一個錯字。你寫的身份,不識別。

def identify() 
    #yield(identity) if block_given? 
    self.identity ||= Identity.new 
    end 

爲什麼你需要產量?當你打電話時,你沒有任何障礙。所以我評論說。 當你需要該塊時,我會檢查,如果有塊。

而你的問題:你沒有返回一個值,因爲你的方法以收益結束。我改變了序列。

+0

謝謝你knut我希望我可以接受多個答案。 –

1

這看起來像是一種用於在類上配置屬性的策略。像下面這樣:

class Foo 
    class << self 
    attr_accessor :config 

    def configure() 
     self.config ||= Configuration.new 
     yield(config) 
    end 
    end 

    class Configuration 
    attr_accessor :hostname 

    def initialize 
     @hostname = 'www.example.com' 
    end 
    end 
end 

此代碼將允許您設置一個初始值可能看起來像:

Foo.config do |config| 
    config.hostname = "www.sometestsite.com" 
end 

然後可以使用配置的情況下在你的類做的方法:

class Foo 
... 
    def self.foo 
     puts "this method is crawling: #{Foo.config.hostname}" 
    end 
... 
end 

它類似於#{} Rails.root /config/environments/development.rb:

ApplicationName::Application.configure do 
... 
... 
end 
0
"#{Person.foo.name}" 

是多餘的。這相當於Person.foo.name.to_s,由於名字是"kibet",並且String#to_s自身返回(我希望!),所以它相當於Person.foo.name

相關問題