Как Ruby пази полета и методи?
Кажете ми всичко, което знаете за instance променливите.
attr_accessor
)instance_variable_get
и компанияКой е класът на "foo"
? На Integer
? На Class
?
Кой е родителят на String
? На Object
? На Class
?
"foo".class == String # true
Integer.class == Class # true
Class.class == Class # true
String < Object # true
Object < BasicObject # true
Class < Module # true
Какво прави instance_eval
?
Изпълнява блока с променен self
.
Как Ruby знае къде да постави метод, дефиниран с def
?
Винаги има текущ клас, в който този метод отива. Той може да се промени
с module
, class
и class_eval
. Всъщност,
дори с instance_eval
, но за това — по-късно.
Може да (пре)дефинирате метод в конркетен обект.
things = [22, :f, 'Sofia']
def things.size
-5
end
def things.asl
"#{self[0]}/#{self[1]}/#{self[2]}"
end
things # [22, :f, "Sofia"]
things.size # -5
things.length # 3
things.asl # "22/f/Sofia"
[].asl # error: NoMethodError
[].size # 0
Собственият клас е достъпен чрез #singleton_class
things = []
def things.answer
42
end
things.singleton_class # #<Class:#<Array:0x9a4ec24>>
things.singleton_class.instance_methods(false) # [:answer]
[].singleton_class.instance_methods(false) # []
Целите числа и символите нямат собствени класове. Това е заради оптимизация. В Ruby интерпретатора, те се представят по много различен начин от всички други обекти.
1_000.singleton_class # error: TypeError
:blah.singleton_class # error: TypeError
Можете да отворите собствения клас на обект с class <<
things = [22, :f, 'Sofia']
class << things
def size
-5
end
def asl
"#{self[0]}/#{self[1]}/#{self[2]}"
end
end
things.asl # "22/f/Sofia"
things.size # -5
Оригиналният метод е достъпен чрез super
.
things = [22, :f, 'Sofia']
class << things
def each
super
yield :P
end
end
aggregated = []
for thing in things
aggregated << thing
end
aggregated # [22, :f, "Sofia", :P]
Някой има ли идея защо super
работи?
things = []
def things.answer
42
end
things.singleton_class # #<Class:#<Array:0xa374f9c>>
things.singleton_class.superclass # Array
Да, eigenclass-ът е наследник на класа на обекта
Вероятно помните, че класови методи могат да се дефинират така:
class Something
def Something.foo() 42 end
def self.bar() 42 end
class << self
def qux() 42 end
end
end
Класовите методи се пазят в собствения клас на класа
class Something
def self.answer() 42 end
end
Something.singleton_class # #<Class:Something>
Something.singleton_class.instance_methods(false) # [:answer]
Помните ли extend
?
module Knowledge
def answer() 42 end
end
class Something
extend Knowledge
end
Something.answer # 42
module Knowledge
def answer() 42 end
end
text = "fourty-two"
text.extend Knowledge
text.answer # 42
Сещате ли се как може да се имплементира?
module Knowledge
def answer() 42 end
end
class Something; end
class << Something
include Knowledge
end
Something.answer # 42
module Knowledge
def answer() 42 end
end
class Something; end
Something.singleton_class.instance_eval { include Knowledge }
Something.answer # 42
Класовите методи на родителя са достъпни в класовите методи на наследника
class Something
def self.answer() 42 end
end
class Other < Something
def self.better_answer() answer * 2 end
end
Other.better_answer # 84
Собственият клас на наследника наследява собствения клас на родителя
class Something; end
class Other < Something; end
Something.singleton_class # #<Class:Something>
Other.superclass.singleton_class # #<Class:Something>
Something.singleton_class == Other.singleton_class.superclass # true
Метакласът на суперкласа е суперкласът на метакласа.
BasicObject
∎