Build-in Objects

Build-in Objects#

Ruby Type System#

Ruby is a dynamically typed and interpreted language. That means that the program is not compiled before the execution to any type of bytecode, and there is no type checking before execution. This may provide to some problems which does not exists in static typed programming languages, but also provides the real freedom for the developer.

Because the variable type is not defined statically and it can change while the program is running, Ruby provides a bunch of methods to determine the class of the instance. Every object has build-in class method, which returns the constant of class name (not a string!). You can check if the object is instance of the given class by running instance_of?(class) method. There is also a function is_a?(class) on every instance, returns true if the class is the class or any of superclass of the given object. The difference between instance_of? and is_a? is that is_a? is checking all superclasses of the variable.
Lets see this on example Server class from previous chapter:

win = WindowsServer.new('kirk', '.starfleet.com')  # WindowsServer is a subclass of Server
#=>* WindowsServer: kirk.starfleet.com *
unix = UnixServer.new('yoda', '.rebelians.org')    # UnixServer is a subclass of Server as well
#=>* UnixServer: yoda.rebelians.org *
win.class                # class of the win variable is WindowsServer
#=>WindowsServer
win.is_a? WindowsServer  # win is a WindowsServer
#=>true
win.is_a? Server         # win is a Server as well, because Server is a superclass of WindowsServer
#=>true
win.is_a? UnixServer     # but is is not an UnixServer
#=>false
win.instance_of? WindowsServer  # win is an instance of WindowsServer class
#=>true
win.instance_of? Server         # but not the instance of Server (instance_of? is not checking superclasses)
#=>false

is_a? method may be replaced by triple equal sign === operator, called case equality operator. The left operand is a class, the right one is an instance. It works like is_a? - checking superclasses as well.

WindowsServer === win
#=>true
Server === win
#=>true

Type Conversion#

Unlike the other languages there is no explicit type conversion system in Ruby. With your own class you may provide methods which converts your object to other classes, if it makes sense. You may call this methods whatever you want, but it is a good practice to use Ruby convention. Thus, to convert object to integer, use to_i method, to_s - to string, to_a - to array, etc.

Let’s see it in example. Consider you want to create an object to keep the IP numbers (you can store it in string or in number, but here is a bit more sophisticated version).

class Ip
  def initialize(p1, p2, p3, p4)
    @p1 = p1; @p2 = p2; @p3 = p3; @p4 = p4
  end
end
ip = Ip.new(192,168,1,10)
#=>#<Ip:0x007faf2b0f78a0 @p1=192, @p2=168, @p3=1, @p4=10>

It is a quite natural to convert the ip to string, giving it human readable, well-known format:

class Ip
  def to_s
    @p1.to_s + "." + @p2.to_s + "." + @p3.to_s + "." + @p4.to_s
  end
end
ip.to_s
#=>"192.168.1.10"

Or even convert it to the 32-bit number:

class Ip
  def to_i
    256*256*256*@p1 + 256*256*@p2 + 256*@p3 + @p4
  end
end
ip.to_i
#=>3232235786

Or represent it as binary or hexadecimal. Notice that to_s method on number object may take an argument - the base, so to convert to binary, use to_s(2), to convert to hex - to_s(16). It is working in the other way as well - to convert “ff” string to integer, add a base to to_i method: ”ff”.to_i(16).

class Ip
  def to_bin
    to_i.to_s(2)
  end
  def to_hex
    to_i.to_s(16)
  end
end
ip.to_bin
#=>"11000000101010000000000100001010"
ip.to_hex
#=>"c0a8010a"