Static and Instance Methods

Since I use Ruby at work now, and since I understand C# syntax much better than I understand Ruby syntax, I occasionally run into things that look like they should or shouldn’t work in Ruby, but surprise me by working (or not working). Today I’ll document the first of these surprises: you can’t call static methods from instance methods in Ruby.

To illustrate what I mean, I’ve made two simple examples:

class HasInstanceMethods
def instance_method
puts "In instance method, the type of `self` is #{self.class}"
end
def self.class_method
puts "In class method, the type of `self` is #{self.class}"
end
def call_class_from_instance
begin
class_method # raise NameError
rescue Exception => e
puts "raised #{e.inspect}"
end
end
def call_self_class_from_instance
self.class.class_method # works
end
end
instance = HasInstanceMethods.new
instance.instance_method # works
HasInstanceMethods.class_method # works
# would raise NoMethodError:
# instance.class_method
instance.call_class_from_instance # NameError
instance.call_self_class_from_instance # works
# ouptut:
# In instance method, the type of `self` is HasInstanceMethods
# In class method, the type of `self` is Class
# raised #<NameError: undefined local variable or method `class_method' for #<HasInstanceMethods:0x007fc88709d380>>
# In class method, the type of `self` is Class

using System;
namespace ConsoleApplication
{
public class HasInstanceAndStaticMethods
{
public static void StaticMethod()
{
Console.WriteLine("Hello from static method");
}
public void InstanceMethod()
{
Console.WriteLine($"Type in instance method is {this.GetType().FullName} ");
}
public void CallStaticMethodFromInstanceMethod()
{
Console.Write("Attempting to call static method from instance method…");
StaticMethod();
Console.WriteLine("… and it succeeded.");
}
}
public class Program
{
public static void Main(string[] args)
{
HasInstanceAndStaticMethods.StaticMethod();
var instance = new HasInstanceAndStaticMethods();
instance.InstanceMethod();
instance.CallStaticMethodFromInstanceMethod();
}
}
}
// Output:
// Type in instance method is ConsoleApplication.HasInstanceAndStaticMethods
// Attempting to call static method from instance method…Hello from static method
// … and it succeeded.

I think that the reasoning behind this difference is that in Ruby, everything is an object, and even classes are objects. Thus, a static method in Ruby is really a method attached to some instance of a class object. The reference self in a Ruby object method refers to the present instance of the class object. In other words, I can’t call static methods in Ruby from instances because they are instance methods on a different object. You can still call them from instance methods with self.class.class_method, but that’s because you’re calling an instance method on the object that represents the current object’s class. Just for fun, since Ruby will let you do whatever you want, let’s make a Ruby class that behaves like a C# class in this respect:

class CSharpStyle
def method_missing method_name, *args
self.class.send(method_name, *args)
end
def self.static_method
puts "hurray for Ruby"
end
def instance_method
print "here goes nothin! "
static_method
end
end
instance = CSharpStyle.new
instance.instance_method
instance.static_method
# Output
# here goes nothin! hurray for Ruby
# hurray for Ruby

view raw
csharp_style.rb
hosted with ❤ by GitHub

That works fine. If a method on an instance of that class is about to raise a no method error, which it would do by calling method_missing on Object, instead my overridden method_missing will fire, and will call the appropriate method on the class. And that’s a great example of something that’s possible, but probably not a good idea – making your program have your own personal syntax quirks might be confusing to future maintainers. But Ruby is fun!

Till next time, happy learning!

-Will

1 thought on “Static and Instance Methods”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s