3 ms·
1. As instance methods always defined in some class: foo = Object.new def foo.hello 12 end foo.method(:hello).owner == foo.singleton
by sergeykish 6y ago
1. As instance methods always defined in some class:
foo = Object.new
def foo.hello
12
end
foo.method(:hello).owner == foo.singleton_class
and class definition is just a syntactic sugar:
Foo = Class.new
def Foo.hello
42
end
Foo.method(:hello).owner == Foo.singleton_class
2. Class method is just a method of objects class
f = Foo.new
f.class.hello
- inopinatus 6y agoIt's dangerous to assume that definition by keyword is syntactic sugar, because there are crucial lexical differences that will bite the novice metaprogrammer on the backside. For example, writing class Foo; end differs from Foo = Class.new since the former will open an existing class, whilst the latter will overwrite the constant with a new class, and then the cref (roughly speaking, constant search path) is different due to the module nesting structure; hence: class Foo MAGIC_NUMBER=42 def self.hello1 MAGIC_NUMBER end end def Foo.hello2 MAGIC_NUMBER end Foo.hello1 #=> 42 Foo.hello2 #=> NameError: uninitialized constant MAGIC_NUMBER and worse: Bar = Class.new do MAGIC_NUMBER = 99 end defines MAGIC_NUMBER as a top-level constant, not as Bar::MAGIC_NUMBER, which is bad enough in itself, but now Foo.hello2 #=> 99 which is the kind of subtle misbehaviour that drives people nuts trying to resolve. Without going into the arcane detail, there are similarly subtle variations that'll show up, involving the default definee (aka the third implicit context), and closures contained in the class definitions. So I'm very sparing in my use of Class.new and even Module.new, I'll restrict them to carefully written framework methods. > Class method is just a method of objects class You'd hope. But look at the mechanics of Kernel#class. Objects don't work from a reference to their (apparent) class, the obj->klass pointer doesn't necessarily go there; it references the head of the linked list of all ancestors, and if you've referred to the singleton in any fashion it'll point to that (absent funny business like prepending the singleton). Then rb_class_real has to iterate along the list skipping the singleton and any ICLASS entries, and assumes the first thing it sees otherwise is the class you meant. The point being that an object's apparent class is defined by the first object in its ancestors list that isn't its singleton class or a included/prepended module. In theory, this should be invariant across the object's lifetime. In practice, Ruby recomputes it each time. The reason for this is that as soon as you reference the singleton of an object, Ruby a) allocates it, and b) updates the obj->klass pointer to be the singleton, not the class it was made from. Also, you can screw with people's assumptions via def foo.class; Object; end, which just demonstrates how wilfully ignoring the Law of Demeter gets you into trouble.