I want to create a simple type of linked object list in ruby; where the instance variable in the class points to another instance of the same type.
A simple note: a word type is a very dangerous word in Ruby, especially if you come from Java. Due to a historical accident, the word is used both in dynamic typing and in static typing to mean two only superficially connected, but very different things.
In dynamic input, a type is a label bound to a value (not a link).
In addition, in Ruby, the concept of type is much broader than in Java. In the minds of Java programmers, the term “type” means the same as “class” (although this is not the case, since interfaces and primitives are also types). In Ruby, "type" means "what can I do with it."
Example: in Java, when I say something like String, I mean that it is a direct instance of the String class. In Ruby, when I say something like String, I mean it is either
- direct instance of class
String or - instance of a subclass of class
String or - an object that matches the
#to_str method or - an object that behaves indistinguishably from a string.
I want to populate and link all the nodes; before calling the constructor and only once. Something we usually did in the Java Static block.
In Ruby, everything is executable. In particular, there is no such thing as a “class declaration”: the body of a class is just code that is called like any other. If you have a list of method definitions in your class, these are not declarations that are read by the compiler and then turned into an object of the class. These are expressions that are performed by the evaluator one by one.
So, you can put any code that you like into the body of the class, and this code will be evaluated when the class is created. In the context of the body of a class, self attached to the class (remember that classes are just objects like any other).
The initialization method is the signature of the constructor in ruby. Are there any rules around them? As in Java, you cannot call another constructor from the constructor if its not the first line (or after calling the class code?)
There are no constructors in Ruby. Constructors are just factory methods (with silly restrictions); there is no reason to have them in a well-designed language if you can just use the (more powerful) factory method.
The construction of an object in Ruby works as follows: the construction of an object is divided into two phases, distribution and initialization. Allocation is performed by an open class method called allocate , which is defined as an instance method of the Class class and, as a rule, is never reevaluated. It simply allocates memory space for the object and sets several pointers, however, the object is not currently in use.
One that the initializer enters: this is an instance method called initialize that sets the internal state of an object and displays it in a consistent, fully defined state that can be used by other objects.
So, to completely create a new object, you need to do the following:
x = X.allocate x.initialize
[Note: Objective-C programmers can recognize this.]
However, since it is too easy to forget to call initialize , and as a general rule, the object must be fully valid after construction, there is a convenient factory method called Class#new that does everything that works for you and looks something like this:
class Class def new(*args, &block) obj = alloc obj.initialize(*args, &block) return obj end end
[Note: in fact, initialize is private, so to circumvent access restrictions you need to use reflection: obj.send(:initialize, *args, &block) ]
This, by the way, is the reason for constructing the object that you call the open class method Foo.new , but you implement the private instance method Foo#initialize , which seems to disable many newbies.
To answer your question: since the initializer method is just a method similar to any other, there are absolutely no restrictions on what you can do with the initializer, in particular, you can call super whenever and wherever you are were often you want.
BTW: since initialize and new are common methods, there is no reason why they should be called initialize and new . This is only an agreement, although rather strong, as it is embodied in the main library. In your case, you want to write a collection class, and it is pretty common for a collection class to propose an alternative factory method called [] , so I can call List[1, 2, 3] instead of List.new(1, 2, 3) .
As a note: one obvious advantage of using conventional object construction methods is that you can instantiate anonymous classes. This is not possible in Java, for any reasonable reason. The only reason it does not work is because the constructor has the same name as the class, and anonymous classes do not have a name, ergo cannot be a constructor.
Although I'm not quite sure why you will need to run something before creating the object. If I didn’t miss something, there should not be a list basically
class List def initialize(head=nil, *tail) @head = head @tail = List.new(*tail) unless tail.empty? end end
for 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?