Ruby: Calling class method from instance
Solution 1
Rather than referring to the literal name of the class, inside an instance method you can just call self.class.whatever
.
class Foo
def self.some_class_method
puts self
end
def some_instance_method
self.class.some_class_method
end
end
print "Class method: "
Foo.some_class_method
print "Instance method: "
Foo.new.some_instance_method
Outputs:
Class method: Foo Instance method: Foo
Solution 2
Using self.class.blah
is NOT the same as using ClassName.blah
when it comes to inheritance.
class Truck
def self.default_make
"mac"
end
def make1
self.class.default_make
end
def make2
Truck.default_make
end
end
class BigTruck < Truck
def self.default_make
"bigmac"
end
end
ruby-1.9.3-p0 :021 > b=BigTruck.new
=> #<BigTruck:0x0000000307f348>
ruby-1.9.3-p0 :022 > b.make1
=> "bigmac"
ruby-1.9.3-p0 :023 > b.make2
=> "mac"
Solution 3
To access a class method inside a instance method, do the following:
self.class.default_make
Here is an alternative solution for your problem:
class Truck
attr_accessor :make, :year
def self.default_make
"Toyota"
end
def make
@make || self.class.default_make
end
def initialize(make=nil, year=nil)
self.year, self.make = year, make
end
end
Now let's use our class:
t = Truck.new("Honda", 2000)
t.make
# => "Honda"
t.year
# => "2000"
t = Truck.new
t.make
# => "Toyota"
t.year
# => nil
Solution 4
If you have access to the delegate method you can do this:
[20] pry(main)> class Foo
[20] pry(main)* def self.bar
[20] pry(main)* "foo bar"
[20] pry(main)* end
[20] pry(main)* delegate :bar, to: 'self.class'
[20] pry(main)* end
=> [:bar]
[21] pry(main)> Foo.new.bar
=> "foo bar"
[22] pry(main)> Foo.bar
=> "foo bar"
Alternatively, and probably cleaner if you have more then a method or two you want to delegate to class & instance:
[1] pry(main)> class Foo
[1] pry(main)* module AvailableToClassAndInstance
[1] pry(main)* def bar
[1] pry(main)* "foo bar"
[1] pry(main)* end
[1] pry(main)* end
[1] pry(main)* include AvailableToClassAndInstance
[1] pry(main)* extend AvailableToClassAndInstance
[1] pry(main)* end
=> Foo
[2] pry(main)> Foo.new.bar
=> "foo bar"
[3] pry(main)> Foo.bar
=> "foo bar"
A word of caution:
Don't just randomly delegate
everything that doesn't change state to class and instance because you'll start running into strange name clash issues. Do this sparingly and only after you checked nothing else is squashed.
Solution 5
self.class.default_make
Comments
-
Peter almost 2 years
In Ruby, how do you call a class method from one of that class's instances? Say I have
class Truck def self.default_make # Class method. "mac" end def initialize # Instance method. Truck.default_make # gets the default via the class's method. # But: I wish to avoid mentioning Truck. Seems I'm repeating myself. end end
the line
Truck.default_make
retrieves the default. But is there a way of saying this without mentioningTruck
? It seems like there should be. -
Peter over 14 yearsI disagree that
default_make
should be an instance method. Even if it's simpler for these examples, it's not the right semantics - the default is a product of the class, not objects that belong to the class. -
phoet over 12 yearsmake should not be an instance method. it's more a kind of factory, that should be bound to the class rather than an instance
-
phoet over 12 yearsi would like to see some shortcut in ruby to call a class method from an instance. ie :>some_class_method instead of self.class.some_class_method
-
Harish Shetty over 12 years@phoet The make word denotes the make of a car(as in Toyota, BMW etc.) englishforums.com/English/AMakeOfCar/crcjb/post.htm. The nomenclature is based on user's requirement
-
Matt Connolly over 12 yearswhile this is the right answer, it's a shame that "self.class" is more typing and less easy to read than the class name "Truck". oh well....
-
Marlen T. B. over 12 years@Peter would you care to explain that in simpler terms? I'm just learning Ruby and Maha's answers seems perfect to me.
-
Peter about 12 years@MarlenT.B. looking back I'm not sure there's too much to be learned here - I was only arguing about where the best place to put the method was, and I don't buy my own argument as strongly anymore! :)
-
drewish over 11 years@MattConnolly, it's relative, if your class name is is
SalesforceSyncJob
then it's shorter ;) -
Gus Shortz about 11 years@MattConnolly, also using
self.class
eliminates the need for search/replacing if you happen to rename the class. -
Matt Connolly about 11 years@GusShortz true. Also, self.class works better if there is a subclass.
-
vish almost 11 yearsI also disagree. Whether something is a class method has nothing to do with "utility". It is about whether the method conceptually applies to the class, or an object of that class. For example, every truck has a different serial number, so serial_number is an instance method (with corresponding instance variable). On the other vehicle_type (which returns "truck") should be a class method because that is a property of all trucks, not a particular truck
-
David West almost 11 yearsI noticed that when I was applying this, I had to define the method before I could call it later in the class. Why is that? Does anybody know if there is a reason the language is designed that way? I'm using Ruby 1.8.7 in this particular instance. Has this changed in the more recent versions?
-
zhon over 10 yearsThis seems to be a response to to the accepted answer rather than an answer to the question.
-
PhilT over 9 years@DavidWest The class is being evaluated so you can't call something before you define it. Are you calling a class method in the class rather than inside a method in the class?
-
Matt Sanders over 8 years@zohn - true, but this is still useful context when considering what to use.
-
nandilugio almost 8 years@MattSanders just use a comment in those cases.
-
Kaiser Shahid over 6 years@hlcs
self.class
is correct to preserve inheritance. even thoughmake1()
is defined inTruck
, it's referencingBigTruck
's class method. -
Seth Jeffery over 5 yearsIf you're in Rails and hate writing
self.class
everywhere, then try this:delegate : some_class_method, to: :class
. -
Chris Harrison over 3 yearsI don't understand what the advantage is to something being 'less typing' or 'shorter'. We are not in a famine where there's a shortage of characters. Something being shorter often means it's more ambiguous.