Що class << self
робити в Рубі ?
Що class << self
робити в Рубі ?
Відповіді:
По-перше, class << foo
синтаксис відкриває foo
одиночний клас (власний клас). Це дозволяє спеціалізувати поведінку методів, викликаних на конкретному об'єкті.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Тепер, щоб відповісти на питання: class << self
відкриває self
«s одноелементний клас, так що методи можуть бути перевизначені для поточного self
об'єкта (який всередині класу або модуля тіла клас або модуль сам ). Зазвичай це використовується для визначення методів класу / модуля ("статичного"):
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
Це також можна записати як скорочення:
class String
def self.value_of obj
obj.to_s
end
end
Або навіть коротше:
def String.value_of obj
obj.to_s
end
Коли всередині визначення функції, self
відноситься до об'єкта, з якого викликається функція. У цьому випадку class << self
відкривається клас Singleton для цього об'єкта; одне використання цього полягає у впровадженні державної машини бідної людини:
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
Так, у наведеному вище прикладі, кожен екземпляр StateMachineExample
має process_hook
псевдонім process_state_1
, але зауважте , як в останньому випадку, він може перевизначити process_hook
(для self
тільки, не зачіпаючи інші StateMachineExample
екземпляри) до process_state_2
. Отже, щоразу, коли абонент викликає process
метод (який викликає переосмислений process_hook
), поведінка змінюється залежно від того, у якому стані він знаходиться.
class << self
для створення методів класу / модуля. Я, мабуть, розширюватиму це використання class << self
, оскільки це набагато ідіоматичніше використання.
a
's, singleton_class
оскільки a
' s class (після зміни inspect
) є унікальним варіантом String
класу. Якби він міняв String
клас однотонних, це впливало б на всі інші String
екземпляри. Що ще дивніше, це те, що якщо ви пізніше повторно відкриєте String
для повторного визначення, inspect
то a
все одно виберете нові зміни.
class << self
означає щось більше, ніж значення self
, встановлене рівним класу синглтон в межах блоку?
Я знайшов надто просте пояснення щодо class << self
,Eigenclass
і різних типах методів.
У Ruby є три типи методів, які можна застосувати до класу:
Методи екземплярів та методи класу майже подібні до їх омонімуму в інших мовах програмування.
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
Інший спосіб звернення до Eigenclass
(що включає методи однотонних) - це за допомогою наступного синтаксису ( class <<
):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
тепер ви можете визначити метод singleton, для self
якого є сам клас Foo
у цьому контексті:
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)
для перевірки.
Зазвичай, наприклад, методи є глобальними. Це означає, що вони доступні у всіх примірниках класу, за яким вони були визначені. На відміну від цього, метод одиночних реалізований на одному об'єкті.
Ruby зберігає методи у класах, і всі методи повинні бути пов'язані з класом. Об'єкт, для якого визначений однотонний метод, не є класом (це екземпляр класу). Якщо лише класи можуть зберігати методи, то як об’єкт може зберігати однотонний метод? Коли створено однотонний метод, Ruby автоматично створює анонімний клас для зберігання цього методу. Ці анонімні класи називаються метакласами, також відомими як однокласні класи або власні класи. Однотонний метод асоціюється з метакласом, який, у свою чергу, асоціюється з об'єктом, для якого був визначений метод синглтон.
Якщо в одному об'єкті визначено кілька однотонних методів, всі вони зберігаються в одному метакласі.
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'…
У наведеному вище прикладі клас << z1 змінює поточне самоврядування, щоб вказати на метаклас об'єкта z1; тоді він визначає метод say_hello в метакласі.
Класи також є об'єктами (екземпляри вбудованого класу під назвою Class). Методи класу - це не що інше, як одиночні методи, пов'язані з об’єктом класу.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Усі об'єкти можуть мати метакласи. Це означає, що класи також можуть мати метакласи. У наведеному вище прикладі клас << self модифікує self, тому він вказує на метаклас класу Zabuton. Коли метод визначений без явного приймача (клас / об'єкт, на якому буде визначений метод), він неявно визначається в межах поточної області, тобто поточного значення self. Отже, метод начинки визначається в метакласі класу Забутон. Наведений вище приклад - це ще один спосіб визначення методу класу. IMHO, краще використовувати синтаксис def self.my_new_clas_method для визначення методів класу, оскільки це полегшує розуміння коду. Наведений вище приклад був включений, щоб ми зрозуміли, що відбувається, коли ми натрапили на синтаксис класу << self.
Додаткову інформацію можна знайти в цій публікації про Ruby Classes .
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[це робить self == thing.singleton_class
у контексті свого блоку] .
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
об'єкт успадковує його #methods
від свого, #singleton_class.instance_methods
а потім від свого #class.instance_methods
.
Тут ми дали hi
«s одноелементний клас метод примірника :a
. Це можна було зробити замість класу << привіт .
hi
«S #singleton_class
має всі методи екземпляра hi
» и #class
є, і , можливо , ще деякі ( :a
тут).
[наприклад, методи речі #class
і #singleton_class
можуть бути застосовані безпосередньо до речі. коли рубін бачить thing.a, він спочатку шукає: визначення методу в thing.singleton_class.instan_methods, а потім у thing.class.instan_methods]
До речі - вони називають об'єкт однокласного класу == metaclass == eigenclass .
А Сінглтон метод це метод , який визначений тільки для одного об'єкта.
Приклад:
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
Методи Сінглтона SomeClass
тест
Методи Синглтона test_obj
тест_2
тест_3
Насправді, якщо ви пишете будь-які розширення на C для своїх проектів Ruby, існує дійсно лише один спосіб визначити метод модуля.
rb_define_singleton_method
Я знаю, що цей власний бізнес просто відкриває всілякі інші питання, щоб ви могли зробити краще, шукаючи кожну частину.
Об'єкти спочатку.
foo = Object.new
Чи можна зробити метод для foo?
Звичайно
def foo.hello
'hello'
end
Що я з цим роблю?
foo.hello
==>"hello"
Просто ще один об’єкт.
foo.methods
Ви отримуєте всі методи Object плюс ваш новий.
def foo.self
self
end
foo.self
Просто об'єкт foo.
Спробуйте побачити, що станеться, якщо ви зробите foo з інших об'єктів, таких як Class і Module. Приклади з усіх відповідей приємно грати, але вам потрібно працювати з різними ідеями чи концепціями, щоб дійсно зрозуміти, що відбувається з тим, як написано код. Отже, зараз у вас є багато термінів.
Singleton, Class, Module, self, Object та Eigenclass виховувались, але Ruby так не називає Object Models. Це більше схоже на метаклас. Річард або __ чому показує вам ідею тут. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html А якщо вас ударить, то спробуйте пошукати модель Ruby Object у пошуку. Два відео, про які я знаю на YouTube, - Дейв Томас та Пітер Купер. Вони також намагаються пояснити це поняття. Дейву знадобилося багато часу, щоб його отримати, тому не хвилюйтеся. Я все ще працюю над цим. Чому б інакше я був тут? Дякуємо за запитання Погляньте також на стандартну бібліотеку. Він має модуль Singleton так само, як і FYI.
Це досить добре. https://www.youtube.com/watch?v=i4uiyWA8eFk