I feel I should add a little here. I'll do it illustratively using code
examples, hopefully people can understand the underlying message.
1. Define a method in a class, create an instance, and call the method
on the instance.
class Foo
# Define a method
# Inside that method, 'self' refers to the instance object.
def asd
p self
end
end
my_foo = Foo.new
my_foo.asd #=> "#<Foo:0x007fec18284568>"
We can't do things like `Foo.asd`, because we haven't added a class
method to Foo.
2. A couple of ways of defining class methods:
# Open the class 'Foo'
# Inside the class definition (but not inside methods),
# 'self' refers to the class object.
class Foo
# Define a class method
# Inside it, 'self' refers to the class object.
def self.asd
p self
end
end
Foo.asd #=> "Foo"
# Like above, but we don't rely on the word 'self'
# to refer to the class object.
class Bar
def Bar.asd
p self
end
end
Bar.asd #=> "Bar"
# Like above, but doing things in different scopes.
class Baz
end
def Baz.asd
p self
end
Baz.asd #=> "Baz"
...etc. Note that you can use 'def obj.meth' to arbitrarily define
methods directly on the 'obj' (whether or not obj is called 'self' or
not).
What this actually does is define the method on obj's singleton class,
which you can think of as a magic class that has exactly one instance:
obj
It might help, at this point, to remember a couple of things:
1) `class Foo; end` opens (or reopens) the definition of class Foo
2) the word 'Foo' in your code is a constant, and the value of that
constant is an object, and that object is_a? Class
3) this also works: Foo = Class.new
So 'Foo' is just another object, and when you call 'Foo.blah' ruby
searches:
1) Foo.singleton_class, for any methods defined directly on Foo, like
#asd
2) Foo's class, Class, for any instance methods defined there, like
#ancestors
3) ... and on up the inheritance tree, through Module, Object, Kernel,
etc.
It is possible to open (or reopen) an object's singleton class using a
special extension syntax:
qux = Object.new
class << qux
def asd
p self
end
end
qux.asd #=> "#<Object:0x007fec182ffdd0>
Note that this is essentially the same as `def qux.asd`, but we can do
other things between the 'class <<' and the 'end', e.g.:
class << qux
private :asd
attr_accessor :bob
end
qux.bob = 123
qux.bob #=> 123
qux.asd #=> NoMethodError: private method `asd' called for
#<Object:0x007fec182ffdd0 @bob=123>
Now, combining this with the fact that a class is just another object,
we can do:
class Qux
class << self
def asd
p self
end
private :asd
attr_accessor :bob
end
end
Qux.bob = 123
Qux.bob #=> 123
Qux.asd #=> NoMethodError: private method `asd' called for Qux:Class
Note that, unless we explicitly write the word 'Class' in the code, or
do some other horrible hackery, we're never adding instance methods to
the Class class. You could do the following:
class Class
def banana
'yes please'
end
end
... which would make the following all work:
Foo.banana #=> "yes please"
Bar.banana #=> "yes please"
Integer.banana #=> "yes please"
Class.banana #=> "yes please"
But that's different from defining 'self.meth' inside a class
definition.
Hope that makes sense.
···
--
Posted via http://www.ruby-forum.com/.