What is the use in class/static methods in ruby? - ruby

Learning ruby and oop in general, I came upon class methods which as far as I understand are like instance methods but are accessed from the class rather than from an object and can have only one running at the same time.
However, I don't understand why you would use a class method versuses a normal method (outside a class) and what is even their use?
For example:
#Why would you use:
class Foo
def self.bar
puts "Class method"
end
end
#Versus simply:
def bar
puts "Normal method"
end
Foo.bar # => Class method
bar # => Normal method
As they both produce the same result?
I'm quite confused about them so please correct if I'm misunderstanding any/everything here.

Your example isn't a good one.
Class methods might deal with managing all instances that exist of a class, and instance methods deal with a single instance at a time.
class Book
def self.all_by_author(author)
# made up database call
database.find_all(:books, where: { author: author }).map do |book_data|
new book_data # Same as: Book.new(book_data)
end
end
def title
#title
end
end
books = Book.all_by_author('Jules Vern')
books[0].title #=> 'Journey to the Center of the Earth'
In this example we have a class named Book. It has a class method all_by_author. It queries some pretend database and returns an array of Book instances. The instance method title fetches the title of a single Book instance.
So the class method managing a collection of instances, and the instance method manages just that instance.
In general, if a method would operate on a group of instances, or is code related to that class but does not directly read or update a single instance, then it probably should be a class method.

This is more an OOP question than a ruby one. Class methods in ruby are used the same as in other OO programming languages. This means:
class methods are run in the context of a class (and have access only to class variables)
instance methods are run in the context of an object (and have access to object's or instance variables)
Here is a better example:
class Foo
def self.bar
puts 'class method'
end
def baz
puts 'instance method'
end
end
Foo.bar # => "class method"
Foo.baz # => NoMethodError: undefined method ‘baz’ for Foo:Class
Foo.new.baz # => instance method
Foo.new.bar # => NoMethodError: undefined method ‘bar
Here you can see that class method is accessed through a class, while instance method is accessed through an instance or object of a class (Foo.new).
Example is copied from here, where you can also find more information on this subject.
Keep in mind: although any code can be put into a class or a instance method, each has it's own use cases and own pros and contras. In OOP we strive for reusable, flexible and readable code, which means that we usually want to put most of the code as structured as instance methods in a sensible domain model.

Just as you said, they are:
"accessed from the class rather than from an object and"
"can have only one running at the same time."
remember, too, that the class is portable

The most important thing is that it keeps your code organized. When you have hundreds of thousands of lines of code, having them all haphazardly throwing stuff around in the same namespace can become a nightmare. Organization is really important, and namespaces are an easy way to get modularity with support from the language.
Somewhat less importantly, class/module methods can share state without leaking it all over the place (e.g. classes can have instance variables), and they can have private support methods to allow for better factoring, while global methods can't effectively be made private.

You have lots of misunderstanding,
In ruby, we can define class and instance method.
Class method is used to do provide processing at class level i.e. data which can only be available at class level or related to all the objects. For example, to count the number of objects belongs to class you need class method. Like
Foo.count
In same way, to process single object you need object method to process a single object like,
obj.save
So, class method is example of singletone design pattern where object can have there own implementation of same method.

Related

Defining a method for an instance of a class

How do you define a method on an instance of a class and this method is only for the instance and not others?
Please can someone provide a use case for this feature?
Defining a singleton method on an object gives you an object with some new properties. That's it, not more, not less.
Sure, you could achieve the same in another way - create a new class with the desired properties and instantiate it, mix in a module that adds the necessary behavior. And in most practical cases you'd probably do just that.
But think about tests for example where you need to mock some object's method (sure, RSpec framework provides a better way to do this, but still). Or you're debugging the code in REPL and would like to mock some method (for example, to avoid unnecessary side effects). In such cases defining a singleton method is the easiest (fastest) way to get things done.
Just don't think about this "feature" as a separate feature. Because it's not. It is just a consequence of how the Ruby object model works - focus on the latter. I strongly recommend this book for that...
Class methods are called on the class itself which is why in the method declaration, it will always state def self.class_method_name.
Whereas instance methods are called on a particular instance of the class (Not class itself) and they are declared like regular methods i.e def instance_method_name.
For example:
class Car
def self.class_method
puts "It's a class method"
end
def instance_method
puts "It's an instance method"
end
end
Car.class_method => "It's a class method"
Cat.instance_method => undefined method 'instance_method' for Car:Class
Car.new.instance_method => "It's an instance method"
Car.new.class_method => undefined method 'class_method' for Car:Class
For the usecase, here is an example from the Rails:
class Car < ApplicationRecord
belongs_to :owner
has_many :passengers
def self.get_cars(owner) # This is a class method
Car.includes(:passengers).where(owner: owner).order(created_at: :desc)
end
end
With Car.get_cars(owner) method, you can get all the cars with your own logic.

Ruby methods called at top of classes

I've seen this a lot in Ruby (started using Ruby for the first time a couple years ago):
class MyAwesomeClass
another_method
def initialize; end
end
And I can't get my head around what type of method another_method is...
Looking at examples, it's sometimes declared as a class method, but usually you call class methods in your code like this:
AnotherClass.another_method
And most importantly you call your methods regardless if they are from another class, module, or inherited class inside another method of your class you use them. For example:
module SomeModule
def some_method; end
end
class AnotherClass
private
def another_method; end
end
class YetAnotherClass
self.yet_another_method; end
end
class MyAwesomeClass < AnotherClass
include SomeModule
def initialize
some_method # method from my included module
another_method # method inherited from AnotherClass
YetAnotherClass.yet_another_method # class method called directly
end
end
So what are these methods that can be called at the top of a class and NOT called inside of another method as my examples above?
Are you able to just call class methods inside another class (that it inherits from) outside of your method calls?
I can't get my head around what type of method another_method is...
There is only one type of method in Ruby: every method in Ruby is an instance method of some module. There is no other type of method.
We may sometimes talk about "class methods" or "singleton methods", but that is just a convenient way of talking about a particular way to use methods. The methods themselves are no different.
Every method in Ruby is an instance method of some module. The question is simply: which module?
We are sometimes talking about class methods, but class methods don't really exist. Class methods are simply singleton methods of an object that happens to be an instance of the Class class.
There is absolutely no difference between
Foo = ''
def Foo.bar; end
and
class Foo; end
def Foo.bar; end
and
module Foo; end
def Foo.bar; end
We call the first one a "singleton method", the second one a "class method", and the third one a "module function", but there is actually no difference between the three. The only difference is that the first object is an instance of the String class, the second object is an instance of the Class class, and the third object is an instance of the Module class, that's it.
Actually, I must confess something: I lied. I wrote that class methods are simply singleton methods of an object that happens to be an instance of the Class class, but in reality … singleton methods don't exist either.
A singleton method is simply a boring old normal instance method of the singleton class.
There is no difference between
foo = ''
def foo.bar; end
and
foo = ''
class << foo
def bar; end
end
There you have it: singleton methods are actually just instance methods of the singleton class, class methods are actually just instance methods of the singleton class of an object that is an instance of the Class class, module functions are actually just instance methods of the singleton class of an object that is an instance of the Module class.
It's just that "instance method of the singleton class of an object that is an instance of the Class class" is annoying to say and write all the time, so we say "class method" instead, knowing full well that there is no such thing.
Looking at examples, it's sometimes declared as a class method, but usually you call class methods in your code like this:
AnotherClass.another_method
Again, there is no such thing as a class method. There is exactly one kind of method, and they are always called the same way:
receiver.method(args)
If the receiver is self, then you can leave it out, and if you have no arguments, you can leave them out, too.
And most importantly you call your methods regardless if they are from another class, module, or inherited class inside another method of your class you use them.
That is not true.
In fact, in your own example, you are calling two methods outside of a method body: Module#private and Module#include, and you seem to have no trouble with those. Other methods that I am sure you have already called outside of a method body are Module#attr_accessor, Kernel#require, or Kernel#puts. In fact, in simple scripts, there is often not a single method definition body at all.
So what are these methods that can be called at the top of a class and NOT called inside of another method as my examples above?
They are instance methods just like any other instance methods, there is absolutely nothing special about them.
Are you able to just call class methods inside another class (that it inherits from) outside of your method calls?
Since class methods don't exist, and these are simply instance methods just like every other instance method, the method lookup algorithm is of course also just the method lookup algorithm for instance methods:
Start with the private internal hidden __klass__ pointer of the receiver. If you can't find the method there …
Get the private internal hidden __superklass__ pointer and repeat.
And that's it. (Yes, okay, there is a tiny bit more to it: if you come to a point where there is no __superklass__ pointer, then you try again with method_missing and the name of the method as an argument, and if you also cannot find that, then you raise a NoMethodError.)
So, let's try that in your example:
class MyAwesomeClass
another_method
end
Okay, first off: what is the receiver? Well, if no receiver is given, then the receiver is always implicitly self. Now, what is self here?
A ha! That is actually the most important question in Ruby, always. At any point in Ruby, you must always know what self is.
Well, we know that inside of a method body, self is the receiver of the message send. So, we can guess: what would make the most sense for self inside of a class definition. The class itself, of course! Let's test that:
what_is_self = class MyAwesomeClass
self
end
p what_is_self
# MyAwesomeClass
Well, looks like we're right. Okay, we know the receiver of the message send is MyAwesomeClass, so what is the first step in our algorithm? We get the private internal hidden __klass__ pointer.
We cannot actually do that in Ruby (it is a private internal hidden implementation detail of the Ruby implementation). But let me assure you that is pretty much always going to be the singleton class. (There are some objects which cannot have singleton classes, and some Ruby implementations optimize the creation of singleton classes so that they are only created when needed, but for all intents and purposes, we can assume that the __klass__ pointer is always the singleton class.)
We look inside the singleton class, and we find no definition of the method another_method. So, we move to the second step of the algorithm: we get the __superklass__ of the singleton class.
The __superklass__ of the singleton class is usually going to be the class of the object. So, in this case, the object is MyAwesomeClass, which is a class, so the class of MyAwesomeClass and the __superklass__ of the singleton class is going to be Class.
Again, we look inside Class and we don't find another_method. Ergo, we get Class's __superklass__, which is Module. We also don't find another_method here, so we move on to Object, which also doesn't have another_method.
Now, it gets interesting again, because Object's __superklass__ pointer is actually Kernel and not BasicObject as you might have thought. (More precisely, it is an include class which shares its method table with the Kernel module, since Kernel is not a class at all and thus cannot be a superclass.)
Kernel also doesn't have a method named another_method, so we get Kernel's __superklass__ (again, technically we are talking about an include class that proxies Kernel and not Kernel itself), which is BasicObject. Finally, BasicObject does not have a __superklass__.
Which means we start aaaaaaaaaaaall the way back from step #1 again, but this time as-if you had written
class MyAwesomeClass
method_missing(:another_method)
end
We do the whole song-and-dance again, and we also never find a method until we get to the very top, to BasicObject, which has a method_missing that roughly looks like this:
class BasicObject
def method_missing(meth, *args)
raise NoMethodError, "undefined method `#{meth}' for #{inspect}", meth, args, receiver: self
end
end
So, if you want your call to another_method to not fail, it needs to be defined anywhere along the whole chain we just walked up:
In MyAwesomeClass's singleton class
In a module that MyAwesomeClass extends
In Class
In a module that Class includes
Or in a module included by that module
In Module
In a module that Module includes
Or in a module included by that module
In Object
In Kernel
Or another module that Object includes
Or in a module that Kernel includes
In BasicObject
In a module that BasicObject includes
Or in a module included by that module
Or maybe the Ruby implementation you are using has an implementation-specific superclass of BasicObject (e.g. MacRuby has Objective-C's NSObject as the superclass of BasicObject)
To illustrate difference between different type of methods, consider this example:
class Foo
puts 'method called outside of method'
def initialize
puts 'initialize called'
end
def instanse_method
puts 'instance method called'
end
def self.clazz_method
puts 'class method called'
end
end
Foo
foo = Foo.new
foo.instanse_method
Foo.clazz_method
What will be the output?
method called outside of method
initialize called
instance method called
class method called
So what are these methods that can be called at the top of a class and NOT called inside of another method as my examples above?
As you can see, any method can be called before initialize method. It's executed when class is loaded.
Just calling
Foo
would be sufficient enough to output:
method called outside of method
(but notice that it was not called multiple times)
Looking at examples, it's sometimes declared as a class method, but usually you call class methods in your code like this: AnotherClass.another_method
It's like static function in PHP. In my example, it's Foo#clazz_method.
And most importantly you call your methods regardless if they are from another class, module, or inherited class inside another method of your class you use them
Usually, you have to include a file that define another class before using its method. But most frameworks like Ruby on Rails, have already built-in autoloading system, so it looks like it's working magically without explicit require or include. But there are times when RoR does not know where your custom classes are. In this case, you have to require the file explicitly before you use it. Well, usually in the beginning of the file.
It'll be easier to understand by looking at it in action.
# Step 1
# Run this in IRB
class MyClass
def self.another_method
puts "Executed when class is loaded to memory"
end
end
# Step 2
# Now when you run the following in IRB after that, its going to execute the
# class method which was defined in its parent class (MyClass)
class MyAwesomeClass < MyClass
another_method # Executed ONCE when the class is loaded to memory for the first
def initialize; end
end
# Now if you instantiate MyAwesomeClass though, it will not print the same as of
# Step 2 as class method :another_method already has been executed when class
# was loaded
awesome1 = MyAwesomeClass.new
The body of a class will be interpreted and executed sequentially & behaves much like you'd expect it inside an instance method. Try putting a puts "Hello World" in the body of your class definition like so:
class MyClass
# Executes when the class is defined in IRB(Loaded to memory)
puts "Hello World"
end

Method call before method in Ruby?

I am new to Ruby and I saw methods defined like:
def method_one
puts "method 1"
end
class MyClass
method_one
def method_two
puts "method 2"
end
end
The way method_one is used reminds me of Python decorators.The output of
c = MyClass.new
c.method_two
is
method 1
method 2
I have been trying to search for more information about this syntax/language feature in the Ruby documentation on the web but I don't know what keywords to search for.
What this is thing called?
TL;DR
This code doesn't do what you think it does. Don't do stuff like this.
Ruby's Top-Level Object
Ruby lets you define methods outside a class. These methods exist on a top-level object, which you can (generally) treat as a sort of catch-all namespace. You can see various posts like What is the Ruby Top-Level? for more details, but you shouldn't really need to care.
In your original post, method_one is just a method defined in the top-level. It is therefore available to classes and methods nested within the top-level, such as MyClass.
Methods in Classes
Despite what you think, the following doesn't actually declare a :method_one class or instance method on MyClass:
class MyClass
method_one
def method_two; end
end
Instead, Ruby calls the top-level ::method_one during the definition of the class, but it never becomes a class method (e.g. MyClass::method_one) or an instance method (e.g. MyClass.new.method_one). There might be a few use cases for doing this (e.g. printing debugging information, test injection, etc.) but it's confusing, error-prone, and generally to be avoided unless you have a really strong use case for it.
Better Options
In general, when you see something like this outside an academic lesson, the programmer probably meant to do one of the following:
Extend a class.
Add a singleton method to a class.
Include a module in a class.
Set up a closure during class definition.
The last gets into murky areas of metaprogramming, at which point you should probably be looking at updating your class initializer, or passing Proc or lambda objects around instead. Ruby lets you do all sorts of weird and wonderful things, but that doesn't mean you should.
I think you're a little mislead; the output of:
c = MyClass.new
c.method_two
is
#<MyClass:0x007feda41acf18>
"method 2"
You're not going to see method one until the class is loaded or if you're in IRB you enter the last end statement.
I would suggest looking into ruby's initialize method.

why are metaclasses created in ruby?

I m trying to understand the Ruby Object Model. I understood that the instance methods are saved in the class rather than in the objects of the class because it removes redundancy. I read that whenever a class is created, a metaclass is created too for the newly created class. the metaclass stores the class methods. ie the singleton methods of the class are located in the metaclass. eg
class MyClass
def hi
'hi object'
end
def self.bye
'bye singleton method'
end
end
for the above MyClass, a metaclass (say #MyClass) is created too. now the method 'hi' is an instance level method and can be called on all the objects of MyClass. method 'bye' is a singleton method of MyClass and it resides in the #MyClass. the reason (i think so) why 'hi' is saved in MyClass rather than all the objects of MyClass is because it avoids redundancy. But we cant have more than one classes named MyClass. So why not store 'bye' in MyClass rather than in #MyClass, since we cant have more than one MyClass. I have absolutely no idea why this is the way it is and i m just trying to understand the reason behind it.
-----UPDATE----
metaclass store the class information like the singleton methods and other stuff. But since a class is a singleton object(its an instance of class Class and is alone of its type) then why not save all the information in the class itself rather than the metaclass.
Just to be super duper clear.
Here is a quick ruby script that explains the question:
#!/usr/bin/env ruby
puts ObjectSpace.count_objects[:T_CLASS] #>> 471
class X
def self.foo
end
def bar
end
end
puts ObjectSpace.count_objects[:T_CLASS] #>> 473
This is what the OP meant by "ObjectSpace.count_objects[:T_CLASS] increments the count by 2." Let's call the extra class the singleton class of X, because that appears to be what Ruby calls it internally.
irb> X
=> X
irb> X.singleton_class
=> <Class: X>
Notice that the #foo method is an instance method of X.singleton_class, not X.
irb> X.instance_methods(false)
=> [:baz]
irb> X.singleton_class.instance_methods(false)
=> [:foo]
So why is :foo stored in X.singleton_class instead of X? Isn't there only ever going to be one X?
I believe the main reason is for consistency. Consider the following, simpler scenario concerning plain instance objects.
car = Car.new
def car.go_forth_and_conquer
end
As #mikej explained superbly, this new method is stored in car's singleton class.
irb> car.singleton_class.instance_methods(false)
=> [:go_forth_and_conquer]
Classes are Objects
Now, classes are objects too. Each class is an instance of Class. Thus, when a class (say, X) is defined, ruby is really creating an instance of Class, and then adding methods to the instance (similar to what we did to car above.) For example, here is an alternative way to create a new class
Car = Class.new do
def go_forth_and_conquer
puts "vroom"
end
end
Car.new.go_forth_and_conquer
Therefore, it is much easier to just reuse the code and do it the same way (i.e. keep foo in X.singleton_class.) This probably requires less effort and will lead to fewer surprises, so no one will ever need to write code to handle Class instances differently from other instances.
Probably Doesn't Matter
You might be thinking that if Ruby did not have singleton classes for instances of Class, there could be some memory savings. However, it sounds to me that where bar is actually stored is an implementation detail that we probably shouldn't count on. Rubinius, MRI, and JRuby could all store methods and instances differently, as long as the behavior is consistent. For all we know, there could be a reasonable implementation of Ruby that doesn't eagerly create singleton classes for class objects, for the exact same reasons you outlined, as long as the overall behavior conforms to the ruby spec. (E.g. an actual singleton class doesn't exist until the #singleton_class method is first invoked.)
This isn't quite an answer to your question, but it might be useful. Two things to think about that might help:
metaclass is not really a good name for what's going on here when you think of how the meta prefix is used in other scenarios. eigenclass which you will see used in other documentation is probably a better name, meaning "an object's own class"
It's not just classes that have an eigenclass, every object does
The eigenclass is used to store methods that are specific to a particular object. e.g. we can add a method to a single String object:
my_string = 'Example'
def my_string.example_method
puts "Just an example"
end
This method can only be called on my_string and not on any other String object. We can see that it is stored in my_string's eigenclass:
eigenclass = class << my_string; self; end # get hold of my_string's eigenclass
eigenclass.instance_methods(false) # => [:example_method]
Remembering that classes are objects, in this context, it makes sense that the methods specific to a particular class should be stored in that class's eigenclass.
Update: actually, there is an eigenclass for the eigenclass. We can see this more easily if we add eigenclass as a method to Object:
class Object
def eigenclass
class << self
self
end
end
end
and then we can do:
irb(main):049:0> my_string.eigenclass
=> #<Class:#<String:0x269ec98>>
irb(main):050:0> my_string.eigenclass.eigenclass
=> #<Class:#<Class:#<String:0x269ec98>>>
irb(main):051:0> my_string.eigenclass.eigenclass.eigenclass # etc!
=> #<Class:#<Class:#<Class:#<String:0x269ec98>>>>
whilst this seemingly creates an infinite regress, this is avoided because Ruby only creates the eigenclasses on as they are needed. I think the name "metaclass" really is a source of part your confusion because you are expecting a "metaclass" to hold some kind of information that it actually doesn't.
The reason really boils down to what self is. For any given method, self is an instance of the object that the method is defined one.
In an instance method, stored on MyClass, self will be the instance of MyClass that you called #hi from. In a class method, self will be the instance of the metaclass (that is, the class itself). Doing it with the metaclass means that the concept of self is unchanged, even when operating on a class, which is itself just a singleton instance of its metaclass.
As per The Ruby Programming Language the class methods, are infact singleton methods on an instance of the class that got same name as the class.
Class Foo
def self.bar
"Am a class method"
end
end
here method self.bar can be depicted as a singleton method on an instance Foo of type Class Foo.
#the following code is just to explain on what actually are class methods called
Foo.bar #=> "Am a class method"
#the call is done on an instance of class Foo which got ref name Foo
We can go on adding more class/singleton/metaclass methods on Foo by
class<<Foo
def self.another_bar
"Am another class method"
end
end
Foo.another_bar #=>"Am another class method"
More formally singleton methods are defined as instance methods of an anonymous eigenclass/meta class.
Though conceptually wrong we can assume classes are objects in this context, so as to have a better grasp.
This concept is there to bring in true Object Oriented - ness in all levels of the language. Objective-C implements class methods in a similar fashion.
In Obj-C metaclasses bails out as classes which contain information about the classes it meta. And the principles of inheritance do apply for meta-classes as well, there super class is its classe's superclasse's metaclass and climbs up so until it reaches the base object, whoe's metaclass is the metaclass itself. More reading on this can be done here.

Static block in Ruby

I have been a Java programmer for a while and I am trying to switch to ruby for a while. I was just trying to develop a small test program in ruby and my intention is something like following.
I want to create a simple linked list type of an object in ruby; where an instance variable in class points to another instance of same type.
I want to populate and link all nodes; before the constructor is called and only once. Something that we'd usually do in Java Static block.
Initialize method is a constructor signature in ruby. Are there any rules around them? Like in Java you cannot call another constructor from a constructor if its not the first line (or after calling the class code?)
Thanks for the help.
-Priyank
I want to create a simple linked list type of an object in ruby; where an instance variable in class points to another instance of same type.
Just a quick note: the word type is a very dangerous word in Ruby, especially if you come from Java. Due to an historic accident, the word is used both in dynamic typing and in static typing to mean two only superficially related, but very different things.
In dynamic typing, a type is a label that gets attached to a value (not a reference).
Also, in Ruby the concept of type is much broader than in Java. In Java programmer's minds, "type" means the same thing as "class" (although that's not true, since Interfaces and primitives are also types). In Ruby, "type" means "what can I do with it".
Example: in Java, when I say something is of type String, I mean it is a direct instance of the String class. In Ruby, when I say something is of type String, I mean it is either
a direct instance of the String class or
an instance of a subclass of the String class or
an object which responds to the #to_str method or
an object which behaves indistinguishably from a String.
I want to populate and link all nodes; before the constructor is called and only once. Something that we'd usually do in Java Static block.
In Ruby, everything is executable. In particular, there is no such thing as a "class declaration": a class body is just exectuable code, just like any other. If you have a list of method definitions in your class body, those are not declarations that are read by the compiler and then turned into a class object. Those are expressions that get executed by the evaluator one by one.
So, you can put any code you like into a class body, and that code will be evaluated when the class is created. Within the context of a class body, self is bound to the class (remember, classes are just objects like any other).
Initialize method is a constructor signature in ruby. Are there any rules around them? Like in Java you cannot call another constructor from a constructor if its not the first line (or after calling the class code?)
Ruby doesn't have constructors. Constructors are just factory methods (with stupid restrictions); there is no reason to have them in a well-designed language, if you can just use a (more powerful) factory method instead.
Object construction in Ruby works like this: object construction is split into two phases, allocation and initialization. Allocation is done by a public class method called allocate, which is defined as an instance method of class Class and is generally never overriden. It just allocates the memory space for the object and sets up a few pointers, however, the object is not really usable at this point.
That's where the initializer comes in: it is an instance method called initialize, which sets up the object's internal state and brings it into a consistent, fully defined state which can be used by other objects.
So, in order to fully create a new object, what you need to do is this:
x = X.allocate
x.initialize
[Note: Objective-C programmers may recognize this.]
However, because it is too easy to forget to call initialize and as a general rule an object should be fully valid after construction, there is a convenience factory method called Class#new, which does all that work for you and looks something like this:
class Class
def new(*args, &block)
obj = alloc
obj.initialize(*args, &block)
return obj
end
end
[Note: actually, initialize is private, so reflection has to be used to circumvent the access restrictions like this: obj.send(:initialize, *args, &block)]
That, by the way, is the reason why to construct an object you call a public class method Foo.new but you implement a private instance method Foo#initialize, which seems to trip up a lot of newcomers.
To answer your question: since an initializer method is just a method like any other, there are absolutely no restrictions as to what you can do whithin an initializer, in particular you can call super whenever, wherever, however and how often you want.
BTW: since initialize and new are just normal methods, there is no reason why they need to be called initialize and new. That's only a convention, although a pretty strong one, since it is embodied in the core library. In your case, you want to write a collection class, and it is quite customary for a collection class to offer an alternative factory method called [], so that I can call List[1, 2, 3] instead of List.new(1, 2, 3).
Just as a side note: one obvious advantage of using normal methods for object construction is that you can construct instances of anonymous classes. This is not possible in Java, for absolutely no sensible reason whatsoever. The only reason why it doesn't work is that the constructor has the same name as the class, and anonymous classes don't have a name, ergo there cannot be a constructor.
Although I am not quite sure why you would need to run anything before object creation. Unless I am missing something, shouldn't a list basically be
class List
def initialize(head=nil, *tail)
#head = head
#tail = List.new(*tail) unless tail.empty?
end
end
for a Lisp-style cons-list or
class List
def initialize(*elems)
elems.map! {|el| Element.new(el)}
elems.zip(elems.drop(1)) {|prv, nxt| prv.instance_variable_set(:#next, nxt)}
#head = elems.first
end
class Element
def initialize(this)
#this = this
end
end
end
for a simple linked list?
You can simply initialize your class variables in the class body, outside of any method declaration. It will behave like a static initializer in Java:
class Klass
##foo = "bar"
def sayFoo
puts ##foo
end
def self.sayFoo
puts ##foo
end
end
The class field ##foo is here initialized to "bar".
In ruby object creation works like this
class Class
def new(*args)
obj= self.allocate # get some memory
obj.send(:initialize) # call the private method initialize
end
end
Object#initialize is just an ordinary private method.
If you wan't something to happen before Object#initialize you have to write your own Class#new. But I see no reason why you would want to do that.
This is basically the same answer paradigmatic gave back in '09.
Here I want to illustrate that the "static initializer" can call other code. I'm simulating a scenario of loading a special user once, upon class initialization.
class Foo
def user
"Thomas"
end
end
class Bar
##my_user = Foo.new.user
def my_statically_defined_user
##my_user
end
end
b = Bar.new
puts b.my_statically_defined_user # ==> Thomas

Resources