Why do this Ruby object have both to_s and inspect methods that appear to do the same thing?
inspect
is used more for debugging and to_s
for end-user or display purposes.
For example, [1,2,3].to_s
and [1,2,3].inspect
produce different output.
Difference between x.inspect and x.to_s in Ruby?
They are usually but not always the same. According to the documentation for Object.inspect()
:
If not overridden, uses the to_s method to generate the string.
So by default, they return the same thing because inspect()
calls to_s()
. Sometimes, however, it makes sense to override to_s()
to do one thing, but when inspecting an object from irb, you want to see more details. So they can be set up to do different things.
In Ruby, why does inspect() print out some kind of object id which is different from what object_id() gives?
The default implementation of inspect
calls the default implementation of to_s
, which just shows the hexadecimal value of the object directly, as seen in the Object#to_s
docs (click on the method description to reveal the source).
Meanwhile the comments in the C source underlying the implementation of object_id
shows that there are different “namespaces” for Ruby values and object ids, depending on the type of the object (e.g. the lowest bit seems to be zero for all but Fixnums). You can see that in Object#object_id
docs (click to reveal the source).
From there we can see that in the “object id space” (returned by object_id
) the ids of objects start from the second bit on the right (with the first bit being zero), but in “value space” (used by inspect
) they start from the third bit on the right (with the first two bits zero). So, to convert the values from the “object id space” to the “value space”, we can shift the object_id
to the left by one bit and get the same result that is shown by inspect
:
> '%x' % (36971870 << 1)
=> "4684abc"
> a = Foo.new
=> #<Foo:0x5cfe4>
> '%x' % (a.object_id << 1)
=> "5cfe4"
Why does Ruby have both private and protected methods?
protected
methods can be called by any instance of the defining class or its subclasses.
private
methods can be called only from within the calling object. You cannot access another instance's private methods directly.
Here is a quick practical example:
def compare_to(x)
self.some_method <=> x.some_method
end
some_method
cannot be private
here. It must be protected
because you need it to support explicit receivers. Your typical internal helper methods can usually be private
since they never need to be called like this.
It is important to note that this is different from the way Java or C++ works. private
in Ruby is similar to protected
in Java/C++ in that subclasses have access to the method. In Ruby, there is no way to restrict access to a method from its subclasses like you can with private
in Java.
Visibility in Ruby is largely a "recommendation" anyways since you can always gain access to a method using send
:
irb(main):001:0> class A
irb(main):002:1> private
irb(main):003:1> def not_so_private_method
irb(main):004:2> puts "Hello World"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> foo = A.new
=> #<A:0x31688f>
irb(main):009:0> foo.send :not_so_private_method
Hello World
=> nil
How do I inspect the methods of a Ruby object?
methods
takes an optional boolean parameter, which specifies whether to also list the methods from the object's class and its superclasses or just the object's singleton methods. So you can do obj.methods(false)
to only get the singleton methods defined on obj
.
If you want the methods defined by the object's class, but not those defined by its superclasses, you can get that by calling instance_methods(false)
on the object's class, so it's obj.class.instance_methods(false)
.
What is the difference between an instance method used to rename an object and a setter method?
#rename
hides the implementation details. You expose a clean and explicit interface - an object can be renamed, but the caller doesn't have to care how it's done. I would recommend to use attr_reader :name
instead of attr_accessor :name
to avoid exposing the setter.
If you expose just #name=
you let the caller to change object internals. It may cause the future changes harder (e.g. if you move name
to a separate object).
Ruby - determining method origins?
Object#method
returns a Method
object giving meta-data about a given method. For example:
> [].method(:length).inspect
=> "#<Method: Array#length>"
> [].method(:max).inspect
=> "#<Method: Array(Enumerable)#max>"
In Ruby 1.8.7 and later, you can use Method#owner
to determine the class or module that defined the method.
To get a list of all the methods with the name of the class or module where they are defined you could do something like the following:
obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}
Determining type of an object in ruby
The proper way to determine the "type" of an object, which is a wobbly term in the Ruby world, is to call object.class
.
Since classes can inherit from other classes, if you want to determine if an object is "of a particular type" you might call object.is_a?(ClassName)
to see if object
is of type ClassName
or derived from it.
Normally type checking is not done in Ruby, but instead objects are assessed based on their ability to respond to particular methods, commonly called "Duck typing". In other words, if it responds to the methods you want, there's no reason to be particular about the type.
For example, object.is_a?(String)
is too rigid since another class might implement methods that convert it into a string, or make it behave identically to how String behaves. object.respond_to?(:to_s)
would be a better way to test that the object in question does what you want.
Related Topics
How to Make Instance Variables Private in Ruby
How to Print Out the Contents of an Object in Rails for Easy Debugging
Using Instance Variables in Class Methods - Ruby
How to Change All the Keys of a Hash by a New Set of Given Keys
How Can an Activerecord::Relation Object Call Class Methods
Geocoder, How to Test Locally When Ip Is 127.0.0.1
What to Use Instead of 'Render :Text' (And 'Render Nothing: True') in Rails 5.1 and Later
Ruby on Rails: How to Explicitly Define Plural Names and Singular Names in Rails
How to Read the Content of an Excel Spreadsheet Using Ruby
Differencebetween Using .Exists, and .Present? in Ruby
Understanding the Gemfile.Lock File
How to Sort a Ruby Hash by Number Value
How to Get Sinatra to Auto-Reload the File After Each Change
Difference Between Has_One and Belongs_To in Rails
Any Success with Sinatra Working Together with Eventmachine Websockets