+- Save-Point (https://www.save-point.org)
+-- Forum: Games Development (https://www.save-point.org/forum-4.html)
+--- Forum: Tutorials (https://www.save-point.org/forum-19.html)
+--- Thread: Ruby - Behind the Scenes (/thread-8781.html)
Ruby - Behind the Scenes - DerVVulfman - 07-15-2023
RUBY BEHIND THE SCENES
A thread for little-known or overlooked properties of Ruby
This topic is meant to bring up lesser-known or considered concepts when programming with Ruby. Each post within will be an individual topic or concept. And this main post an index of sorts. Currently the initial post also includes a discussion on the constructor, a feature common to both C++ and Ruby.
Other concept will be forthcoming, but not on a scheduled basis
CONSTRUCTORS (and a little bit on Destructors)
Something both C++ and RUBY Share
Tucked away within the structure of the Class object for Ruby are constructors. Like C++, a constructor is a predefined method built into the Class object, and its primary purpose is to initialize essential variables and content required before use.
And like C++, you will find the use of constructors within any any class within Ruby, Ruby's constructor the aptly named 'initialize' method. Indeed, you do not need to create an initialize method when you create a class as one exists by default. In fact, you do not need to call the initialize method for any class as it is created upon the class object's creation
Ergo, a statement of $scene_mummy = Scene_Imhotep.new which creates the $scene_mummy object actively triggers its initialize method at start, whether the coder included one within the code or not.
Of course, you need not take my word for it. Other experts have made mention:
EDUCBA on Ruby Constructors Wrote:A constructor in Ruby is part of a class attribute, and it is a predefined method that depends on us we want to use a constructor or not; the primary purpose of a constructor is to initialize the essential variables and required things before making any method calls of the class, the good thing about the constructor is we do not need to call constructor function for initialization of the class it will be initialized on the object creation from the class, to use the constructor method in any class of Ruby we can use initialize method. It will get called on object creation from the class.
Here, EDUCBA clearly states the that a Constructor is a predefined method meant to to initialize the essential variables when a Class object is created. And that the Initialize method is invoked upon the Class's creation
And this is repeated within sites such as: DesignciseA class constructor in Ruby is defined by adding an "initialize" method to the class like so Geeks for Geeks: A constructor is defined using the initialize and def keywords.
I would be remiss if I didn't provide a rebuttal argument: Ruby Doc: Programming Ruby: In Ruby, these objects are created by calling a constructor, a special method associated with a class. The standard constructor is called new.
But that seems to be more the exception, and not the rule. And when searching ruby-doc, there is little else other than claiming you need a 'C-Constructor" being .new to invoke the initialize method. Ruby-Doc suggests that '.new' is a constructor, rather than a keyword (or 'method' according to our RPG help files) that triggers the creation of a class... which in turn invokes the constructor. But later within an index covering built-in classes and modules, it does refer to .new as a method that "Creates a new anonymous module. "
● ● ●
The creation of a constructor within Ruby is different then when coding with C++. This because the constructor within C++ is actually written when declaring the name of the class. Yet it is still automatically invoked when the class is created.:
Geeks for Geeks Wrote:Constructor in C++ is a special method that is invoked automatically at the time of object creation. It is used to initialize the data members of new objects generally. The constructor in C++ has the same name as the class or structure. Constructor is invoked at the time of object creation. It constructs the values i.e. provides data for the object which is why it is known as constructors.
Even the online Ruby documentation states, "Whenever Ruby creates a new object, it looks for a method named initialize and executes it." Even here, ruby-doc admits that the Initialize method is invoked when any class is created. And yes, this is true for C++, though again C++'s constructor is part of the class name. https://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/objinitialization.html
One could consider it appearing thus:
RUBY:
class Fruit def initialize(kind, condition, fee) ...
C++
class Fruit { int kind; int condition; double fee; fruit() ...
}
Similar, but different. Also note the intuitiveness of Ruby that you need not immediately declare the data-types of the variables as you do with C++ and other languages. But that's another topic.
● ● ●
Now that the discussion of the existence of the constructor and how it is immediately invoked when a Class object is created, it is now time for discussion on their use. The previous talk was prologue to discuss what the Initialize method actually was. And now, for its base execution.
Since the initialize method is the built-in constructor method for all Class objects, it is not so much an inherited method as it is a hidden method. So it is subject to the aliasor alias_method commands as any normal method, this without baggage of parent_class/child_class inheritance. Even if a script which you may have encountered does not appear to have initializemethods within their Class objects, they exist none-the-less.
EXAMPLE TEST SCRIPTS:
RPGMaker XP Test
Place below Scene_Debug and above Main
Code:
#==============================================================================
class Scene_Title
#--------------------------------------------------------------------------
alias scene_title_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_title_initialize
end
end
#==============================================================================
class Scene_Map
#--------------------------------------------------------------------------
alias scene_map_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_map_initialize
end
end
#==============================================================================
class Scene_Item
#--------------------------------------------------------------------------
alias scene_item_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_item_initialize
end
end
#==============================================================================
class Scene_End
#--------------------------------------------------------------------------
alias scene_end_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_end_initialize
end
end
#==============================================================================
class Scene_Battle
#--------------------------------------------------------------------------
alias scene_battle_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_battle_initialize
end
end
#==============================================================================
class Scene_Shop
#--------------------------------------------------------------------------
alias scene_shop_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_shop_initialize
end
end
#==============================================================================
class Scene_Name
#--------------------------------------------------------------------------
alias scene_name_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_name_initialize
end
end
#==============================================================================
class Scene_Gameover
#--------------------------------------------------------------------------
alias scene_gameover_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_gameover_initialize
end
end
#==============================================================================
class Scene_Debug
#--------------------------------------------------------------------------
alias scene_debug_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_debug_initialize
end
end
RPGMaker VX/Ace Test
Place below Scene_Gameover and above Main
Code:
#==============================================================================
class Scene_Title < Scene_Base
#--------------------------------------------------------------------------
alias scene_title_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_title_initialize
end
end
#==============================================================================
class Scene_Map < Scene_Base
#--------------------------------------------------------------------------
alias scene_map_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_map_initialize
end
end
#==============================================================================
class Scene_Item < Scene_Base
#--------------------------------------------------------------------------
alias scene_item_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_item_initialize
end
end
#==============================================================================
class Scene_End < Scene_Base
#--------------------------------------------------------------------------
alias scene_end_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_end_initialize
end
end
#==============================================================================
class Scene_Shop < Scene_Base
#--------------------------------------------------------------------------
alias scene_shop_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_shop_initialize
end
end
#==============================================================================
class Scene_Name < Scene_Base
#--------------------------------------------------------------------------
alias scene_name_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_name_initialize
end
end
#==============================================================================
class Scene_Debug < Scene_Base
#--------------------------------------------------------------------------
alias scene_debug_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_debug_initialize
end
end
#==============================================================================
class Scene_Battle < Scene_Base
#--------------------------------------------------------------------------
alias scene_battle_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_battle_initialize
end
end
#==============================================================================
class Scene_Gameover < Scene_Base
#--------------------------------------------------------------------------
alias scene_gameover_initialize initialize
#--------------------------------------------------------------------------
def initialize
p "I am initializing " + (self.type).to_s
scene_gameover_initialize
end
end
Notice the use of (self.type) in the example. Self is, itself, a keyword in ruby that grants you access to the current object, or a pointer to the current object if you wish to use C++ vernacular. The use of self in this instanceallows you to access the class object itself within the statement, while the .type method permits access to the name (or type) of the Class Object. The 'type' instance method is part of the innate Object class structure, and is connected to the 'kind_of? ' (aka 'is_a?') instance methods of the Object class as well. Object is itself a structure within Ruby and other Object Oriented Programming and encapsulates modules, classes and the like... a separate topic on hierarchy itself.
These examples apply simple messages whereby the classes rely upon the pre-defined initializemethods and do not have any defined by RPGMaker. So there are no message pops within "Scene_Skill" as it has a defined initializemethod. But you will see message pops when exiting any menu to enter any map, the "Scene_Map" class utilizing its already existing constructor.
Ergo, the supplied example scripts can illustrate that the default initialize methods do exist within all Classes, even when undefined. And the use of the alias methods within the example scripts reveal their existence.
But this discussion is not about the use of Alias in itself. This discussion is about constructors and the initializemethod. The use of Alias is another conversation of its own.
● ● ●
Now C++ does include another built in feature within the Class Object, it being destructors. Destructors too are predefined methods, their primary purpose to handle the removal of the objects when the Class object ends. And they too are built into Ruby, but not related to the dispose method and is not subject to alias.
That constructors and destructors are predefined within Ruby and C++ grants the coder more flexibility and means they have no need to invoke or define them (utilizing def within Ruby) within their custom Class code.