Ruby學習_self

來源:互聯網
上載者:User

self上下文

     Ruby的self有和Java的this相似之處,但又大不相同。Java的方法都是在執行個體方法中引用,所以this一般都是指向當前對象的。而Ruby的代碼逐行執行,所以在不同的上下文(context)self就有了不同的含義,先來看看常見的context self都代表哪些

# 這個位置位於top level context,代表Object的預設對象main
p self # => main
p self.class # => Object
@self1 = self

# 因為所有自訂類都位於main context之中,所以這是Object的執行個體方法
# 同時也可以說是一個全域方法
def a_method
  @self2 = self
  p self
  # => main,因為有了執行個體變數@self1和@self2,所以列印出來的不是main這個字元
  # => 但仍然是main對象,注釋掉4,8行即可看到效果
  p @self1 == @self2 # => true
end

# 下面是一個關於類中不同內容相關的self
class Person
  p self # => Person,代表當前類
 
  def instance_method
    p self # => #<Person:0xb7818fdc>,代表當前類的執行個體
  end
 
  def self.class_method
    p self # => Person,和第16行一樣代表當前類(這是類方法的context),它們是相等的
  end
end

m = Person.new
def m.hello
  p self # => 代表m這個單例對象
end

m.hello

 

    上面唯寫了在類中的self,其實在module也是一樣的。通過上面代碼你可以發現,self一直引用著它所在位置內容相關的執行個體/類。

    self顯式/隱式

    你可以先試著運行下面代碼,看看有什麼意外發生沒有

 class Person
  attr_accessor :name
 
  def set_name(your_name)
    name = your_name
  end
end

m = Person.new
p m.name
m.set_name('today')
p m.name # => 猜是什麼

 

    如果你猜是today就大錯特錯了,答案是nil,為什麼是nil呢,在第5行,我明明調用的是attr_accessor產生的name=方法賦值的啊,你可以在前面加上self試試,代碼如你預期的一樣執行了。在這種情況下name = your_name並沒有去調用attr_accessor產生的xx=方法,而是將name當作了一個局部變數,如果顯式的指定self,就沒有問題了。

    讀到這,你是不是認為以後這種情況就一直用顯式self去調用就好了,其實不然,下面的代碼仍會說明一些問題

 class Person

  public
  def get_my_secret1
    my_secret # => 隱式
  end
 
  def get_my_secret2
    self.my_secret # => 顯式
  end

  private
  def my_secret
    p 'something...'
  end
 
  def self.secret
    p 'nothing'
  end
end

m = Person.new
#m.my_secret # => private method error
Person.secret # => nothing
m.get_my_secret1 # => something
m.get_my_secret2 # => private method error
 

    上面代碼說明:

    第一個問題,顯式self不可以調用private(protected的也一樣)方法,而隱式的可以,這說明隱式更具有靈活性,但由於上面隱式調用也同時存在一定的“誤解”,所以讀者應該明白他們之間的區別,以便更好的使用。

    第二個問題,self的方法不受private限制,其實我在這故意誤導了讀者,因為self的方法是類方法,而許可權修飾符只對執行個體方法生效,所以private的類方法也可以直接存取。

    self“怪異”寫法

    下面代碼被我個人稱為怪異寫法,因為平時用不到,但偶爾會看到,但看起來又不太直觀,這裡列舉一下

 class Person
  def metaclass
    class << self
      self
    end
  end
 
  def metaclass2
    self
  end
end

a = Person.new

b = a.metaclass
c = a.metaclass2

# 首先要明白,類Person是Class的一個“執行個體”,a是Person的一個執行個體
# 這裡b也是一個Person類,但它是獨一無二的,即你修改Person不會影響到b,反之亦然
p b # => #<Class:#<Person:0xb76f3800>>
p b.class # => Class

class Person
  def hello
    p 'hello Person'
  end
end

class << b
  def hello
    p 'hello b'
  end
end

b.hello # => hello b

p c # => #<Person:0xb76f3800>
p c.class # => Person

c.hello # => hello Person
 

    還有一個

 class Person
  def self.hello
    p 'hello'
  end
 
  class << self
    # 看了最上面self和context的關係,你應該知道這個self代表是Person類
    # 在這裡為Person添加方法,其實也就是為Person添加類方法,和上面的self.hello異曲同工
    def work
      p 'hard work'
    end
  end
end

Person.work

 

 

轉自:http://ilstar.blogbus.com/logs/59782933.html
 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.