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
You're doing it the right way. Class methods (similar to 'static' methods in C++ or Java) aren't part of the instance, so they have to be referenced directly.
On that note, in your example you'd be better served making 'default_make' a regular method:
#!/usr/bin/ruby
class Truck
def default_make
# Class method.
"mac"
end
def initialize
# Instance method.
puts default_make # gets the default via the class's method.
end
end
myTruck = Truck.new()
Class methods are more useful for utility-type functions that use the class. For example:
#!/usr/bin/ruby
class Truck
attr_accessor :make
def default_make
# Class method.
"mac"
end
def self.buildTrucks(make, count)
truckArray = []
(1..count).each do
truckArray << Truck.new(make)
end
return truckArray
end
def initialize(make = nil)
if( make == nil )
@make = default_make()
else
@make = make
end
end
end
myTrucks = Truck.buildTrucks("Yotota", 4)
myTrucks.each do |truck|
puts truck.make
end
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.
One more:
class Truck
def self.default_make
"mac"
end
attr_reader :make
private define_method :default_make, &method(:default_make)
def initialize(make = default_make)
@make = make
end
end
puts Truck.new.make # => mac
self.class.default_make
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
Similar your question, you could use:
class Truck
def default_make
# Do something
end
def initialize
super
self.default_make
end
end