In the program below, the method of the child class calls the private method of the parent class.
class Parent
private
def new_name
'Private Method'
end
end
class Child < Parent
def get_parent_name
puts new_name
end
end
obj = Child.new
obj.get_parent_name
Ruby is said to be object oriented language so the line
puts new_name
accesses the private method of parent class. Internally, how does it call the method? As being a Object Oriented Programming Language, it should call it using an object. But an object cannot access a private method.
Private methods in Ruby are inherited. So if you define private method for Parent, it's also present in Child.
Answering you comment on the first answer.
There is an implicit reference to the current instance within the class. When you do puts new_name inside get_parent_name what you are really doing is calling new_name on the current instance.
Well in fact, when you say private what Ruby does is to avoid calling the method using an explicit object reference.
class Klass
private
def new_name
'Private Method'
end
def new_name_pub__wrong
self.new_name # won't work since using an explicit object reference
end
def new_name_pub__ok
new_name # will work but means basically the same as self.new_name
end
end
Then in your case this is just basic OOP
Child call new_name on the instance (as I said above), finding none it will crawl the inheritance hierarchy and find the Parent new_name (private methods are visible for all sub-classes)
In Ruby, you can make the receiver implicit, in which case it is implied to be self. This is similar to Self, Java, C#, Scala and many other object-oriented languages, and unlike Smalltalk, which always requires an explicit receiver.
Also, you seem to have no trouble at all understanding how the private puts method inherited from Kernel gets called, but there is no difference between puts and new_name, so why are you having trouble with one but not the other?
Ruby use send to call the method. You can do it yourself and access any private method:
puts obj.send(:new_name)
Here is the doc
Related
I'm near the finish of the Ruby track in Code Academy, and I'm curious about a peculiar thing: I was under the impression that a class is a repository of constants, methods, etc... and that in order to access most of them, you would first need to create an instance of that class or in some cases the methods of themselves can be invoked (as in they are all technically part of the global object). And then I saw something like this:
#Worked
Time.now
I understood as this as the method [now] of instance of class [Time] being invoked. I then tried to invoke the method on its own:
#Failed
now
and that failed, and I assumed that while a method can be created in the general scope [as part of the global object], if it relies on initialized variables of "parent" class, it cannot be called on its own, because it would not know which object to search for those initialized variables. Following that I created a test class:
class Clock
def initialize
#hours = 1
#minutes = 30
end
def showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
#this worked
watch = Clock.new
watch.showTime
#this failed
showTime
I then just created a basic method (assuming it's in the global level)
def mymethod
puts "The mighty METHOD!"
end
#Works
mymethod
and calling this method the way I did, without referencing the global object worked. So... the questions I have are as follows:
How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
Why can't I call the method [now] on its own? Am I right that it relies on resources that it cannot find when called this way?
Why could I not call the method showTime on its own? But if I define any method on the "global" level I can access it without referencing the global object
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object class and hence seem to be globally available. Why? From any context Object is always in the class hierarchy of self and hence private methods on Object are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class class and may have singleton methods.
class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods are
class A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name) as follows
str = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on Enumerable) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again.
This is known as a class method. If CodeAcademy didn't cover it, that's a shame. Here's some examples:
# basic way
class Foo
def self.bar; :ok; end
end
Foo.bar # => :ok
# alternate syntax
class Foo
class << self
def bar; :ok; end
end
end
# alternate syntax, if Foo class already exists
def Foo.bar; :ok; end
# alternate approach if Foo class already exists
Foo.class_exec do
def bar; :ok; end
end
# to define a class method on an anonymous 'class' for a single instance
# you won't need to use this often
Foo.new.singleton_class.class_exec do
def bar; :ok; end
end
# to define a class method on an instance's actual class
Foo.new.class.class_exec do
def bar; :ok; end
end
Another way to get class methods is to extend a module.
module FooMethods
def bar; :ok; end
end
module Foo
extend FooMethods
end
Foo.bar # => :ok
Note that with Modules, the methods are always defined as instance methods. This way they can be either extended into class scope or included into instance scope. Modules can also have class methods, using the exact same syntax / examples as shown above with classes. However there's not such as easy to load a module's class methods via include or extend.
How can [Time.now] be called in this fashion? Shouldn't there be an
instance of Time first created?
The Time.now method is a class method, not an instance method and therefore can be called directly on the Time class rather than an instance of it Time.new
Class methods are defined on the class themselves using the self keyword:
class Time
def self.now
# code
end
end
Time.now # works
Why can't I call the method [now] on its own? Am I right that it
relies on resources that it cannot find when called this way?
When you call a method "on its own" you're actually implicitly calling it on self:
self.now
The above is the same as just doing:
now
Why could I not call the method showTime on its own? But if I define
any method on the "global" level I can access it without referencing
the global object
You defined the showTime method on a specific class so you have to send that method to that class. When you define a method in the "global" scope you're implicitly defining it on self and the subsequent call to mymethod is actually self.mymethod so it will work.
Time.now is a class method.
To define a class method, you need to define the method with self. : def self.method_name
class Clock
#hours = 1
#minutes = 30
def self.showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
Clock.showTime
#=> The time is: 1:30
If you want to call now on its own, you can do so inside Time class :
class Time
puts now
#=> 2017-01-19 22:17:29 +0100
end
I understand that Ruby's #initialize method is private. However, what stumps me is how Ruby makes the method private.
We normally define classes like this:
class Cat
def initialize(name)
#name = name
end
def say_name
puts #name
end
end
where #initialize seems to be defined publicly alongside #say_name. How does Ruby manage to make #initialize private after the class definition?
Yukihiro Matsumoto (the inventor of Ruby) has said:
#initialize is, by its design, supposed to be called only from within #new to separate per object/class initialization from the #new, thus you don't have to redefine #new. When you need/want to redefine #new, it's a sign of a bad design, I believe.
One of the reason #initialize being private is to tell you bad design.
So in summary it's a built in feature of Ruby that #initialize is automatically private and it's so developers won't easily call it outside of the .new class method.
Very interesting question! I researched it and found some interesting things about Ruby, though I did not find the exact answer you're looking for.
initialize is a private instance method that is meant to be redefined on most objects. It comes from BasicObject, the Ruby class from which all objects and classes inherit.
Any new class you create in Ruby will have a private instance method called initialize:
class Q ; end
Q.private_instance_methods.include?(:initialize)
=> true
That instance method is inherited from BasicObject#initialize:
q = Q.new
q.method(:initialize)
=> #<Method: Q(BasicObject)#initialize>
And the method itself is not defined in Ruby, it comes from the C source of the language:
q.method(:initialize).source_location
=> nil
This is what that looks like in the Ruby source code (object.c file):
rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
rb_obj_dummy is basically a no-op function. Which makes sense because the expectation is that you'll override initialize with your own implementation code in your class.
All that said, your original question was about why initialize doesn't become a public method when you define it in the public space in your class definition. I don't know. Normally if you do that for any other method it will become a public method:
class Q
private
def my_private_method() "private" end
end
Q.new.my_private_method
NoMethodError: private method `my_private_method' called for #<Q:0x007fc5ea39eab0>
class Q
def my_private_method() "now i'm a public method" end
end
Q.new.my_private_method
=> "now i'm a public method"
So I guess somewhere else deep in the source code defining a method named "initialize" is handled differently from other methods. I couldn't find it, but maybe someone else can.
module Test
private
def secret
puts '<>'
end
end
include Test
secret #it works
Test.secret #it fails: "private method `secret' called for Test:Module (NoMethodError)"
Is there some design reason why private works this way? I am aware that I can use
private_class_method :secret
to block also the first call but I want to know whatever there is some use case for private in modules.
A generally good way to start understanding what a private method is in Ruby is to think of it as a method that can only be called implicitly. That means that the object that is receiving the method shouldn't be explicitly specified:
my_private_method # Implicit call, this is OK.
self.my_private_method # Explicit call, this won't work.
Using this simple approach you can ensure (somewhat) that private methods won't be callable on objects other than self. For example:
my_private_method # Calling private method on self, this is OK.
other_object.its_private_method # Calling other object's private method, this won't work.
Now, when you have a module that defines a private method you first need to include it somewhere in order to be able to use the method. What you did in you example is include the module at the topmost level. When you do that Ruby includes the module in the Object class. That means that your secret method is now a private method of all Ruby objects, and since all Ruby objects will have the private secret method, you can implicitly call it from anywhere in your program now:
secret #=> "<>"
class MyClass
secret
end #=> "<>"
To give you an idea, your secret method will behave pretty much like the puts method does (also one of Object's private methods). You can't call puts explicitly on an object, but you can use it anywhere in your program. And that is one of the reasons you could want to have private methods in a module.
Another reason could be to implement methods only the including module or class is meant to use, for example:
module M
private
def my_private_method
"This is private."
end
end
class C
include M
def my_public_method
"<#{my_private_method}>"
end
end
c = C.new
c.my_public_method #=> "<This is private.>"
c.my_private_method #=> This won't work.
In simple words, you're including the module in the class you're currently in. And you're running methods from the class you're currently in.
So it works - like it should.
class CA
include Test
end
CA.new.secret # THIS shouldn't work
include Test
secret # THIS should
I'm trying to get a good Ruby coding style. To prevent accidently calling a local variable with the same name, I'm always using self. where appropriate. But now I stumbled over this:
class MyClass < ActiveRecord::Base
before_validation :sanitize_user_data
private
def sanitize_user_data
self.sanitize_name # with ".self" it's a problem, without it's not!
end
def sanitize_name
unless self.name.nil?
self.name.gsub!(/\s+/, ' ')
self.name.strip!
end
end
end
The above code results in an error
private method sanitize_name called
but when removing self. and just using sanitize_name, it works. Why's that?
This happens because private methods cannot be called with an explicit receiver, and saying self.sanitize_name is explicitly specifying the object (self) that should receive sanitize_name, rather than relying on the implicit receiver (which is also self).
You can't avoid this, you either need to call plain old sanitize_name without an explicit receiver, or do self.send(:sanitize_name). I'm not sure that always explicitly specifying self is really "good style", but that's subjective. If you want to ensure you're calling a method instead of a variable, add parenthesis:
def a; "method"; end
a = "variable"
a() #=> "method"
a #=> "variable"
Why's that?
By definition. Private methods can only be invoked by a receiverless message send, that's the definition of what private means.
Ruby as an Object Oriented Language. What that means is whatever message I send, I strictly send it on some object/instance of class.
Example:
class Test
def test1
puts "I am in test1. A public method"
self.test2
end
def test2
puts "I am in test2. A public Method"
end
end
makes sense I call method test2 on self object
But I cannot do this
class Test
def test1
puts "I am in test1. A public method"
self.test2 # Don't work
test2 # works. (where is the object that I am calling this method on?)
end
private
def test2
puts "I am in test2. A private Method"
end
end
When test2 is public method I can call it on self (fair enough, a method sent to self object). But when test2 is private method I cannot call it on self. So where is the object that I am sending method on?
The Problem
In Ruby, private methods can't be called directly with an explicit receiver; self doesn't get any special treatment here. By definition, when you call self.some_method you are specifying self as the explicit receiver, so Ruby says "No!"
The Solution
Ruby has rules for its method lookups. There may be a more canonical source for the rules (other than going to the Ruby source), but this blog post lays out the rules right at the top:
1) Methods defined in the object’s singleton class (i.e. the object itself)
2) Modules mixed into the singleton class in reverse order of inclusion
3) Methods defined by the object’s class
4) Modules included into the object’s class in reverse order of inclusion
5) Methods defined by the object’s superclass, i.e. inherited methods
In other words, private methods are first looked up in self without requiring (or allowing) an explicit receiver.
where is the object that I am sending method on
It's self. Whenenver you don't specify a receiver, the receiver is self.
The definition of private in Ruby is that private methods can only be called without a receiver, i.e. with an implicit receiver of self. Interestingly, it didn't bother you at all with the puts method which is also a private instance method ;-)
Note: there's an exception to this rule. Private setters can be called with an explicit receiver, as long as the receiver is self. In fact, they must be called with an explicit receiver, because otherwise there would be an ambiguity with local variable assignments:
foo = :fortytwo # local variable
self.foo = :fortytwo # setter
self means the current instance of the object you are in.
class Test
def test1
self
end
end
Calling Test.new.test1 will return something like #<Test:0x007fca9a8d7928>.
This is the instance of the Test object you are currently using.
Defining a method as private means it can only be used inside the current object.
When using self.test2, you are going outside of the current object (you get the instance) and you call the method.
So you are calling a private methods as if you were not in the object, which is why you can't.
When you don't specify self, you remain inside the current object.
So you can just call the method. Ruby is smart enough to know that test2 is a method and not a variable and to call it.
This has been changed in Ruby 2.7 (December 2019): self.foo() is now also valid for a private method foo.
References:
https://rubyreferences.github.io/rubychanges/2.7.html#selfprivate_method
https://bugs.ruby-lang.org/issues/11297
https://bugs.ruby-lang.org/issues/16123