Điều gì class << self
làm trong của Ruby ?
Điều gì class << self
làm trong của Ruby ?
Câu trả lời:
Đầu tiên, class << foo
cú pháp mở ra foo
lớp đơn (eigenclass). Điều này cho phép bạn chuyên môn hóa hành vi của các phương thức được gọi trên đối tượng cụ thể đó.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Bây giờ, để trả lời câu hỏi: class << self
mở ra self
's lớp singleton, do đó phương pháp có thể được định nghĩa lại cho hiện tại self
đối tượng (mà bên trong một cơ thể lớp hoặc mô-đun là lớp hoặc mô-đun riêng của mình ). Thông thường, điều này được sử dụng để định nghĩa các phương thức lớp / mô-đun ("tĩnh"):
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
Điều này cũng có thể được viết như một tốc ký:
class String
def self.value_of obj
obj.to_s
end
end
Hoặc thậm chí ngắn hơn:
def String.value_of obj
obj.to_s
end
Khi bên trong một định nghĩa hàm, self
tham chiếu đến đối tượng mà hàm đang được gọi với. Trong trường hợp này, class << self
mở lớp singleton cho đối tượng đó; một cách sử dụng đó là để thực hiện bộ máy nhà nước của một người nghèo:
class StateMachineExample
def process obj
process_hook obj
end
private
def process_state_1 obj
# ...
class << self
alias process_hook process_state_2
end
end
def process_state_2 obj
# ...
class << self
alias process_hook process_state_1
end
end
# Set up initial state
alias process_hook process_state_1
end
Vì vậy, trong ví dụ trên, mỗi trường hợp StateMachineExample
đã được đặt process_hook
bí danh process_state_1
, nhưng lưu ý làm thế nào trong trường hợp sau, nó có thể xác định lại process_hook
( self
chỉ, không ảnh hưởng đến các StateMachineExample
trường hợp khác ) process_state_2
. Vì vậy, mỗi lần người gọi gọi process
phương thức (gọi là có thể xác định lại process_hook
), hành vi sẽ thay đổi tùy thuộc vào trạng thái của nó.
class << self
, để tạo các phương thức lớp / mô-đun. Tôi có thể sẽ mở rộng về việc sử dụng đó class << self
, vì đó là một cách sử dụng thành ngữ hơn nhiều.
a
là singleton_class
từ a
'lớp s (sau khi thay đổi inspect
) là một biến thể độc đáo của String
lớp. Nếu nó thay đổi String
lớp singleton, nó sẽ ảnh hưởng đến tất cả các String
trường hợp khác . Điều kỳ lạ hơn nữa là nếu sau này bạn mở lại String
để xác định lại inspect
thì a
vẫn sẽ nhận được những thay đổi mới.
class << self
nghĩa là bất cứ điều gì nhiều hơn giá trị của self
được đặt bằng với lớp singleton trong phạm vi của khối không?
Tôi tìm thấy một lời giải thích siêu đơn giản về class << self
, Eigenclass
và các loại phương pháp khác nhau.
Trong Ruby, có ba loại phương thức có thể được áp dụng cho một lớp:
Các phương thức sơ thẩm và phương thức lớp gần như tương tự với các ngôn ngữ lập trình khác.
class Foo
def an_instance_method
puts "I am an instance method"
end
def self.a_class_method
puts "I am a class method"
end
end
foo = Foo.new
def foo.a_singleton_method
puts "I am a singletone method"
end
Một cách khác để truy cập Eigenclass
(bao gồm các phương thức singleton) là với cú pháp sau ( class <<
):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
bây giờ bạn có thể định nghĩa một phương thức singleton cho chính self
lớp Foo
đó trong ngữ cảnh này:
class Foo
class << self
def a_singleton_and_class_method
puts "I am a singleton method for self and a class method for Foo"
end
end
end
foo.singleton_class.instance_methods(false)
để kiểm tra.
Thông thường, các phương thức thể hiện là các phương thức toàn cầu. Điều đó có nghĩa là chúng có sẵn trong tất cả các trường hợp của lớp mà chúng được định nghĩa. Ngược lại, một phương thức singleton được thực hiện trên một đối tượng.
Ruby lưu trữ các phương thức trong các lớp và tất cả các phương thức phải được liên kết với một lớp. Đối tượng mà một phương thức singleton được định nghĩa không phải là một lớp (nó là một thể hiện của một lớp). Nếu chỉ các lớp có thể lưu trữ các phương thức, làm thế nào một đối tượng có thể lưu trữ một phương thức singleton? Khi một phương thức singleton được tạo, Ruby sẽ tự động tạo một lớp ẩn danh để lưu trữ phương thức đó. Các lớp ẩn danh này được gọi là siêu dữ liệu, còn được gọi là các lớp đơn hoặc eigenclass. Phương thức singleton được liên kết với siêu dữ liệu, lần lượt, được liên kết với đối tượng mà phương thức singleton được xác định.
Nếu nhiều phương thức singleton được định nghĩa trong một đối tượng, tất cả chúng đều được lưu trữ trong cùng một siêu dữ liệu.
class Zen
end
z1 = Zen.new
z2 = Zen.new
class << z1
def say_hello
puts "Hello!"
end
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
Trong ví dụ trên, lớp << z1 thay đổi bản thân hiện tại để trỏ đến siêu dữ liệu của đối tượng z1; sau đó, nó định nghĩa phương thức say_hello trong siêu dữ liệu.
Các lớp cũng là các đối tượng (các thể hiện của lớp dựng sẵn có tên là Class). Các phương thức lớp không có gì khác hơn các phương thức singleton được liên kết với một đối tượng lớp.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Tất cả các đối tượng có thể có siêu dữ liệu. Điều đó có nghĩa là các lớp cũng có thể có siêu dữ liệu. Trong ví dụ trên, lớp << tự sửa đổi bản thân để nó trỏ đến siêu dữ liệu của lớp Zabuton. Khi một phương thức được định nghĩa mà không có bộ thu rõ ràng (lớp / đối tượng mà phương thức sẽ được xác định), nó được định nghĩa ngầm trong phạm vi hiện tại, nghĩa là giá trị hiện tại của bản thân. Do đó, phương thức công cụ được định nghĩa trong siêu dữ liệu của lớp Zabuton. Ví dụ trên chỉ là một cách khác để định nghĩa một phương thức lớp. IMHO, tốt hơn là sử dụng cú pháp def self.my_new_clas_method để xác định các phương thức lớp, vì nó làm cho mã dễ hiểu hơn. Ví dụ trên được đưa vào để chúng tôi hiểu những gì đang xảy ra khi chúng tôi bắt gặp lớp << cú pháp tự.
Thông tin bổ sung có thể được tìm thấy tại bài viết này về Ruby Classes .
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[nó làm self == thing.singleton_class
trong bối cảnh của khối] .
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
đối tượng kế thừa nó #methods
từ nó #singleton_class.instance_methods
và sau đó từ nó #class.instance_methods
.
Ở đây chúng ta đã hi
's lớp singleton phương pháp dụ :a
. Nó có thể đã được thực hiện với lớp << hi thay vào đó.
hi
là #singleton_class
có tất cả các phương pháp dụ hi
's #class
có, và có thể một số chi tiết ( :a
ở đây).
[phương pháp ví dụ của điều #class
và #singleton_class
có thể được áp dụng trực tiếp vào điều. khi ruby nhìn thấy thing.a, trước tiên, nó tìm kiếm: một định nghĩa phương thức trong thing.singleton_group.instance_methods và sau đó trong thing. class.instance_methods]
Nhân tiện - họ gọi lớp singleton của đối tượng == metaclass == eigenclass .
Phương thức sing singleton là phương thức chỉ được xác định cho một đối tượng.
Thí dụ:
class SomeClass
class << self
def test
end
end
end
test_obj = SomeClass.new
def test_obj.test_2
end
class << test_obj
def test_3
end
end
puts "Singleton's methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton's methods of test_obj"
puts test_obj.singleton_methods
Phương pháp của Singleton
kiểm tra
Các phương thức test_obj của Singleton
kiểm tra_2
kiểm tra_3
Trong thực tế nếu bạn viết bất kỳ phần mở rộng C nào cho các dự án Ruby của mình thì thực sự chỉ có một cách để xác định phương thức Mô-đun.
rb_define_singleton_method
Tôi biết việc tự kinh doanh này chỉ mở ra tất cả các loại câu hỏi khác để bạn có thể làm tốt hơn bằng cách tìm kiếm từng phần.
Đối tượng đầu tiên.
foo = Object.new
Tôi có thể làm một phương pháp cho foo không?
Chắc chắn rồi
def foo.hello
'hello'
end
Tôi phải làm gì với nó?
foo.hello
==>"hello"
Chỉ là một đối tượng khác.
foo.methods
Bạn nhận được tất cả các phương thức Object cộng với phương thức mới của bạn.
def foo.self
self
end
foo.self
Chỉ là đối tượng foo.
Hãy thử xem điều gì sẽ xảy ra nếu bạn tạo foo từ các Đối tượng khác như Class và Module. Các ví dụ từ tất cả các câu trả lời rất hay để chơi nhưng bạn phải làm việc với các ý tưởng hoặc khái niệm khác nhau để thực sự hiểu những gì đang diễn ra với cách viết mã. Vì vậy, bây giờ bạn có rất nhiều điều khoản để xem xét.
Singleton, Class, Module, self, Object và Eigenclass đã được đưa lên nhưng Ruby không đặt tên cho Model Model theo cách đó. Nó giống như Metaclass hơn. Richard hoặc __why cho bạn thấy ý tưởng ở đây. http://viewourcecode.org/why/hacking/ectingMetac gốmClearly.html Và nếu bạn bị thổi bay thì hãy thử tìm kiếm Mô hình đối tượng Ruby trong tìm kiếm. Hai video mà tôi biết trên YouTube là Dave Thomas và Peter Cooper. Họ cố gắng giải thích khái niệm đó quá. Dave đã mất một thời gian dài để có được nó vì vậy đừng lo lắng. Tôi cũng vẫn đang làm việc với nó. Tại sao tôi lại ở đây? Cảm ơn câu hỏi của bạn. Cũng hãy xem thư viện tiêu chuẩn. Nó có một Mô-đun Singleton giống như một FYI.
Điều này là khá tốt. https://www.youtube.com/watch?v=i4uiyWA8eFk