How is it that this works? When the following is run "hi from class" is printed twice. What is going on inside ruby to make this behave like this? Am I NOT in fact making an instance method for class
class Class
def foo
puts "hi from class"
end
end
Class.foo
x = Class.new
x.foo
I don't know whether you're aware of that, but when you do class Class ... end, you're not creating a new class named Class, you're reopening the existing class Class.
Since Class is the class that all classes are instances of that means that Class is an instance of itself. And because of that you can call any instance methods of Class directly on Class the same way you can on any other class.
Related
In this code:
class Dog
def self.bark
print "woof"
end
end
class Little_dog < Dog
end
Little_dog.bark
the method is inherited from a generalised class that references self. But the next patch of code:
class Dog
def Dog.bark
print "woof"
end
end
class Little_dog < Dog
end
Little_dog.bark
also works. I was expecting it to give me an error, but it didn't.
How does self refer to the class method under class inheritance? Why does the little_dog class have a class method bark in the second example when I only defined it as a class method of Dog?
self is widely used in Ruby Metaprogramming.
From Metaprogramming Ruby book:
Every line of Ruby code is executed inside an object—the so–called
current object. The current object is also known as self, because
you can access it with the self keyword.
Only one object can take the role of self at a given time, but no
object holds that role for a long time. In particular, when you call a
method, the receiver becomes self. From that moment on, all instance
variables are instance variables of self, and all methods called
without an explicit receiver are called on self. As soon as your code
explicitly calls a method on some other object, that other object
becomes self.
So, in code:
class Dog
# self represents the class object i.e: Dog. Which is an instance of Class.
# `bark` will be treated as class method
def self.bark
print "woof"
end
end
can also be written as:
class Dog
# Dog is an instance of Class.
# `bark` will be treated as class method
def Dog.bark
print "woof"
end
end
Inheritance allows a subclass to use features of its parent class. That's why you can access bark method in Little_dog class since it is inherited Dog class:
class Little_dog < Dog
# has `bark` as a class method because of Dog
end
Ruby style guide tip: In Ruby it's considered as a best practice to use CamelCase convention for naming classes and modules.
When you're defining class method it actually doesn't matter if you use
Dog.bark
or
self.bark
Both method defines class method which will be inherited by subclasses.
Only difference is when you will be changing name of class Dog to something else, like BigDog - when you use Dog.bark it obviously needs to be changed to BigDog.bark.
When using self method definition, self.bark will still work.
In Metaprogramming Ruby book, I can across the concept of superclass and class.
Here is the reference image:
As I understand: Class has an instance method defined superclass , which can be called by any new class defined (Here MyClass)
My question is:
The parent Class has superclass as Module but the object MyClass has superclass as Object . Why does superclass of Myclass is Object but not Module ? If it is by design, why is it designed this way?
If you define a new class Foo in Ruby, then indeed, it is an instance of Class class, and Foo.class.superclass is Module as expected. But since you are asking not about the ancestors of Foo.class, but directly about the ancestors of Foo, then know that
class Foo
end
is the same as writing
class Foo < Object
end
In other words, a newly defined class will by default become a subclass of Object class, unless otherwise specified. Of course, you could manually define
class Bar < Module
end
in order to create an explicit subclass of Module class. Descendants of Module class have specific qualities and are of special use in Ruby. Note that class Class cannot be subclassed.
I'm ruby newbie, I am learning some ruby's basic knowledge such as class inheritance.
I write some snippets to deepen my understanding, but the bellow 2 snippets make me very confused.
class Object
def hello_o
puts "Hello in Object"
end
hello_o
end
This one print "Hello in Object" while
class A
def hello_a
puts "Hello in A"
end
hello_a
end
this one throw me an error:
undefined local variable or method hello_a' for A:Class
Why? I think both A and Object is class.
With the first example, you defined an instance method hello_o on class Object, and called it from Object, which is an instance of Class class, which inherits Object class, so it worked.
With your second example, you defined an instance method hello_a of class A, and tried to call it from A, which is an instance of Class class, which does not inherit A class, so it failed.
You are dynamically adding a method to the Object class, which is the root of the object hierarchy. therefore, anything that subclasses Object (which is everything, implicitly) will have that method available to it. That's why you're allowed to call it in your class definition.
class Object
def hello_o
puts "Hello in Object"
end
hello_o
end
class A
end
A.hello_o # this will work
the ruby book I'm reading has confused me a bit. If I do the following, I understand completely why the code throws an error;
class Person
def show_name
puts #name
end
end
person = Person.new
person.show_name
Person.show_name #(note the capital P) this line falls over
It throws an error stating that the Person class does not have a method called show_name, because it is an instance method. I understand this completely. The book then throws in this example;
class Class
def add_accessor(accessor_name)
self.class_eval %Q{attr_accessor :#{accessor_name}}
end
end
class Person
end
person = Person.new
Person.add_accessor :name #note the capital P
Person.add_accessor :age #capital P here too
person.name = "Mikey"
person.age = 30
puts person.name
and goes on to state how cool it is that you can add methods to classes dynamically. What I don't understand is why I am suddenly allowed to call the "add_accessor" method as a class method (with a capital P) when the method itself isn't defined as such? I thought all class methods had to be declared like this?
class Math
def self.PI
3.141
end
end
puts Math.PI
Is anyone able to enlighten me?
Ruby classes are objects like everything else to. Your Person class is really an object of class Class, which in turn inherits from class Module. When you add a method to class Class as an instance method, you are providing a new method for all classes.
If you had declared it with a def in Person, it would not be callable without an object. To add class methods for one class, but not all, you must prepend the method name with self or the name of the class:
class Person
def instance_method
end
def self.class_method
end
def Person.other_class_method
end
end
When you declare the method as self.class_method you are declaring your method to be a singleton method on the class object. self in a class or module declaration refers to the class object, which is why self. and Person. are the same.
When dealing with Ruby, just remember everything is an object, everything has methods. There are no functions in Ruby either, despite appearances to the contrary. Methods and objects, always.
Look at this:
person.instance_of?(Person) #=> true
Person.instance_of?(Class) #=> true
You have defined an instance method add_accessor for all the instances of the class Class, so Person class can use that method because it is an instance of Class.
I recommend yout to take a look at metaprogramming and Ruby Object Model.
Hoep this helps
You're extending the Class class, and all of your classes, like Person, are instances of Class (Yes, classes are instances of the Class class. They're ordinary objects).
So when you call Person.add_accessor, you're calling the instance method Class#add_accessor.
because Person (with capital P ) is an instance of the class Class.
Rails has these cool properties that seem to be actually methods. For example:
class SomeController < ApplicationController
before_filter :authenticate!
end
What are these actually called and how would you create your own? For example, in one of my models I want to be able to have a dynamic property that selects an internal method for processing some results:
class MyModel < ActiveRecord::Base
active_method :some_class_method
end
How would I set this up so I can set active_method like that and be able to access the active_method symbol as an instance var?
Edit for elaboration:
So give this starter below, I need to figure out how to define "selected_method" so that it defines a accessor or instance variable so "called_selected_method" calls "method_b".
class MyClass
selected_method :method_b
def call_selected_method
end
private
def method_a
puts 'method_a'
end
def method_b
puts 'method_b'
end
end
c = MyClass.new
c.call_selected_method # should put 'method_b'
It's actually just a method call to a method defined on the class. before_filter is provided by a ruby Module, which is mixed in to ActionController.
Creating your own methods similar to before_filter is as easy as:
Define a class method on your Class
Call that method in any concrete implementations of your class.
Some example code:
class MyClass
class << self
def some_function(*args)
# your code here
end
end
some_function "foo"
end
If you wanted to abstract it further, you can put the class method in to a Module, and then include that module in to your class(es).
UPDATE:
In relation to your asking of how to get a call of some_function to set an instance variable on your class, you can't, as class methods cannot affect specific instances of that class.
I have to wonder, though... you're writing a method that will just act as a proxy to your other method, and would be hard-coded in to the class definition. That offers no benefit to you, and would just make your code redundantly complicated.