Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Làm chủ từ khóa `self` trong Ruby: Hướng dẫn rõ ràng cho mọi Developer

Hôm nay tôi muốn nói về self. Nếu bạn lập trình Ruby một thời gian, bạn có thể đã internalize khái niệm self. Bất cứ khi nào đọc hoặc viết chương trình, self ở đó trong sau đầu bạn.

Nhưng cho Rubyists kém experienced hơn, self có thể baffling. Nó luôn thay đổi, nhưng không bao giờ explicit trong code. Bạn chỉ được mong đợi biết.

Nhiều vấn đề beginners gặp phải do không hiểu self. Nếu bạn từng "mất" instance variable hoặc băn khoan data nào visible cho mixin, đó là vì bạn không hiểu self trong ngữ cảnh đó.

Trong bài này, chúng ta sẽ xem self trong nhiều tình huống hàng ngày.

self là gì?

Bạn có thể nghe người ta nói mọi thứ trong Ruby là object. Nếu đó là đúng, nghĩa là mọi đoạn code bạn viết "thuộc về" object nào đó.

self là biến đặc biệt trỏ tới object "sở hữu" code đang thực thi hiện tại. Ruby dùng self khắp nơi:

  • Cho instance variables: @myvar
  • Cho method và constant lookup
  • Khi định nghĩa methods, classes và modules.

Về lý thuyết, self khá rõ ràng. Nhưng thực tế, dễ nảy sinh tình huống tricky. Đó là lý do tôi viết bài này.

Ví dụ của self

Chúng ta sẽ bước qua vài ví dụ. Nếu cái đầu hơi basic, cứ đọc tiếp. Chúng tiến bộ hơn.

Bên trong instance method

Trong code dưới, reflect là instance method. Nó thuộc về object tạo qua Ghost.new. Vì vậy self trỏ tới object đó.

class Ghost def reflect self end end g = Ghost.new g.reflect == g # => true 

Bên trong class method

Với ví dụ này, reflect là class method của Ghost. Với class method, chính class "sở hữu" method. self trỏ tới class.

class Ghost def self.reflect self end end Ghost.reflect == Ghost # => true 

Nó hoạt động giống hệt với "class" method bên trong module. Ví dụ:

module Ghost def self.reflect self end end Ghost.reflect == Ghost # => true 

Nhớ rằng, class và module được đối xử như object trong Ruby. Vì vậy hành vi này không khác lạ so với instance method behavior ở ví dụ đầu.

Bên trong class hoặc module definition

Một tính năng khiến Ruby phù hợp với framework như Rails là bạn có thể execute arbitrary code bên trong class/module definition. Khi bạn đặt code bên trong class/module definition, nó chạy như code Ruby bình thường. Sự khác biệt thực sự duy nhất là giá trị của self.

Như bạn thấy dưới, self trỏ tới class hoặc module đang được định nghĩa.

class Ghost self == Ghost # => true end module Mummy self == Mummy # => true end 

Bên trong mixin methods

Mixed-in methods hành xử giống như "normal" instance hoặc class method về self. Điều này hợp lý. Nếu không mixin không thể interact với class bạn mix vào.

Instance methods

Mặc dù method reflect được định nghĩa trong module, self của nó là instance của class nó được mix vào.

module Reflection def reflect self end end class Ghost include Reflection end g = Ghost.new g.reflect == g # => true 

Class methods

Khi chúng ta extend class để mix in class methods, self hành xử đúng như normal class methods.

module Reflection def reflect self end end class Ghost extend Reflection end Ghost.reflect == Ghost # => true 

Bên trong metaclass

Khả năng bạn đã thấy shortcut phổ biến này để định nghĩa nhiều class methods cùng lúc.

class Ghost class << self def method1 end def method2 end end end 

Cú pháp class << foo thực sự khá thú vị. Nó cho phép truy cập metaclass của object - còn gọi là "singleton class" hoặc "eigenclass". Tôi dự định cover metaclass sâu hơn trong bài sau. Nhưng hiện tại, bạn chỉ cần biết metaclass là nơi Ruby lưu methods unique cho một object cụ thể.

Nếu bạn truy cập self từ bên trong block class << foo, bạn nhận được metaclass.

class << "test" puts self.inspect end # => #<Class:#<String:0x007f8de283bd88> 

Bên ngoài bất kỳ class nào

Nếu bạn chạy code bên ngoài bất kỳ class nào, Ruby vẫn cung cấp self. Nó trỏ tới "main", là instance của Object:

puts self.inspect # => main