Static block in Ruby

I've been programming Java for a while, and I'm trying to switch to ruby ​​for a while. I was just trying to develop a small ruby ​​test program, and my intention is something like the following.

  • 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.
  • 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.

  • 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?)

Thanks for the help. -Priyank

+4
source share
4 answers

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?

+19
source

You can simply initialize class variables in the class, 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 here is initialized to "bar" .

+2
source

In creating an object, ruby ​​works as follows

 class Class def new(*args) obj= self.allocate # get some memory obj.send(:initialize) # call the private method initialize end end 
  • Object#initialize is a regular private method.
  • If you have nothing to do before Object#initialize , you should write your own Class#new . But I see no reason why you want to do this.
0
source

This is basically the same paradigmatic answer that was given in '09.

Here I want to illustrate that a “static initializer” can call different code. I simulate a special user load script once, after the class is initialized.

 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 
0
source

All Articles