CSC/ECE 517 Fall 2007/wiki1 4 ar: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
<center><h1>Private Method Invocation in Ruby</h1></center>
<center><h1>Private Method Invocation in Ruby</h1></center>


<p>
 
<i>
<i>


Line 9: Line 9:


<h2> <u>Ruby’s Access Control Mechanisms</u></h2>
<h2> <u>Ruby’s Access Control Mechanisms</u></h2>
<p>
 
Ruby has three levels of access controls – Private, Protected and Public.
Ruby has three levels of access controls – Private, Protected and Public.
<i>Public methods</i> – can be accessed by anyone. In Ruby, public is default access control, except initialize method which is private by default.
<i>Public methods</i> – can be accessed by anyone. In Ruby, public is default access control, except initialize method which is private by default.
</b>Protected methods</b> – can be accessed only by the defining class and its subclasses. Access is kept within the family.
<b>Protected methods</b> – can be accessed only by the defining class and its subclasses. Access is kept within the family.
Private methods – can be accessed only by the objects of the defining class. The explicit receiver is always self (the current object), which means that it is impossible to invoke another object’s private methods and variables directly even if the object has the same class type as the caller.  
Private methods – can be accessed only by the objects of the defining class. The explicit receiver is always self (the current object), which means that it is impossible to invoke another object’s private methods and variables directly even if the object has the same class type as the caller.  
<p>
 
 


Example -1:
Example -1:
def foo1
def foo1
   self.bar
   self.bar
end
end
def foo2
def foo2
   bar
   bar
end
end
def bar
def bar
   puts "In bar"
   puts "In bar"
end
end
private :bar
private :bar


Output :
Output :
foo2  -> 'In bar'
foo2  -> 'In bar'
foo1  -> 'NoMethodError: private method `bar' called for main:Object'
foo1  -> 'NoMethodError: private method `bar' called for main:Object'


<p>
 
Example -1 shows that private methods can be called only with an implicit receiver. Even calling a private method using self throws NoMethodError.
Example -1 shows that private methods can be called only with an implicit receiver. Even calling a private method using self throws NoMethodError.
Private methods cannot be invoked using an explicit receiver. But we use self to invoke writer methods else the method will be interpreted as an assignment to a local variable.
Private methods cannot be invoked using an explicit receiver. But we use self to invoke writer methods else the method will be interpreted as an assignment to a local variable.
Line 42: Line 40:
Comparing the private method invocation in C++ and Ruby
Comparing the private method invocation in C++ and Ruby
The private methods in C++ can be invoked by another object of the same class whereas Ruby does not allow explicit receiver for private methods.
The private methods in C++ can be invoked by another object of the same class whereas Ruby does not allow explicit receiver for private methods.
Example -2:
Example -2:


Line 55: Line 54:


Example -2 shows that a private method can be called by any instance of the same class.
Example -2 shows that a private method can be called by any instance of the same class.
Example -3
Example -3


Line 67: Line 67:
       end
       end
     end
     end
Example -3 shows, when calling a private method a receiver cannot be specified in Ruby.
Example -3 shows, when calling a private method a receiver cannot be specified in Ruby.
So it can be concluded that in C++, “private” defines “private to the class”, while in Ruby it states “private to this instance”.
So it can be concluded that in C++, “private” defines “private to the class”, while in Ruby it states “private to this instance”.
Bypassing private method invocation in Ruby
 
<h2>Bypassing private method invocation in Ruby</h2>
 
Example -4:
Example -4:


Line 78: Line 81:
  end
  end
end
end
t = Test.new
t = Test.new
t.send( "print_hello" )
t.send( "print_hello" )


Output: Hello everyone!
Output: Hello everyone!
Example -4 shows that it is possible to access private methods in Ruby through “send” function. Declaring as private is only a guideline in Ruby than a strict rule. There are workarounds to access those private methods. The advantage of such workarounds allows testing of private methods but it is a bad practice since private methods are internals of a class.
Example -4 shows that it is possible to access private methods in Ruby through “send” function. Declaring as private is only a guideline in Ruby than a strict rule. There are workarounds to access those private methods. The advantage of such workarounds allows testing of private methods but it is a bad practice since private methods are internals of a class.
Since private methods have a loophole of security, alternative good practice would be to use accessor functions. In accessor functions, we implement the getter and setter methods for the private attributes, thereby providing the required security.
Since private methods have a loophole of security, alternative good practice would be to use accessor functions. In accessor functions, we implement the getter and setter methods for the private attributes, thereby providing the required security.
The advantages of using accessor function are – Flexibility and Maintainability
The advantages of using accessor function are – Flexibility and Maintainability
• Since the implementation is confined to the accessor functions, any future changes needs to be made at a single point.
• Since the implementation is confined to the accessor functions, any future changes needs to be made at a single point.
• Any type checking that needs to be done can be included within the accessor function. This prevents the object from getting into an inconsistent state.
• Any type checking that needs to be done can be included within the accessor function. This prevents the object from getting into an inconsistent state.
In general, it is a good programming practice to use accessor functions instead of invoking private methods in Ruby.
In general, it is a good programming practice to use accessor functions instead of invoking private methods in Ruby.

Revision as of 23:32, 14 September 2007

Private Method Invocation in Ruby


Ruby's private methods can be called only on "self" (the calling object). They can't be applied to other objects of the same class, even from within the class definition. In class today, I opined that it is rarely if ever necessary to call a private method on another object of the same class. Try to find Java or C++ examples on the Web where a private method is called on another object. Decide if this is good design, or if it would be better performed by using accessor functions, from the standpoint of elegance or maintainability. If you cannot find any such examples (or even if you can), try to find arguments about why one should not invoke private methods on other objects. Analyze these arguments; can you find weaknesses?

Ruby’s Access Control Mechanisms

Ruby has three levels of access controls – Private, Protected and Public. Public methods – can be accessed by anyone. In Ruby, public is default access control, except initialize method which is private by default. Protected methods – can be accessed only by the defining class and its subclasses. Access is kept within the family. Private methods – can be accessed only by the objects of the defining class. The explicit receiver is always self (the current object), which means that it is impossible to invoke another object’s private methods and variables directly even if the object has the same class type as the caller.


Example -1:

def foo1

 self.bar

end def foo2

 bar

end def bar

 puts "In bar"

end private :bar

Output : foo2 -> 'In bar' foo1 -> 'NoMethodError: private method `bar' called for main:Object'


Example -1 shows that private methods can be called only with an implicit receiver. Even calling a private method using self throws NoMethodError. Private methods cannot be invoked using an explicit receiver. But we use self to invoke writer methods else the method will be interpreted as an assignment to a local variable.

Comparing the private method invocation in C++ and Ruby The private methods in C++ can be invoked by another object of the same class whereas Ruby does not allow explicit receiver for private methods.

Example -2:

   class Base {
   private:
       void foo();
   public:
       void spam(Base *otherObject) {
           foo();              // this is allowed
           otherObject->foo(); // and so is this
       }
   };

Example -2 shows that a private method can be called by any instance of the same class.

Example -3

   class Base
   private
     def foo; end
   public
     def spam(otherObject)
       foo             # this is allowed in Ruby (self is implicit)
       self.foo        # Throws a error – NoMethodError private method `foo' called for #<Base:0x66b0dcc>
       otherObject.foo # Throws a error 
     end
   end

Example -3 shows, when calling a private method a receiver cannot be specified in Ruby. So it can be concluded that in C++, “private” defines “private to the class”, while in Ruby it states “private to this instance”.

Bypassing private method invocation in Ruby

Example -4:

class Test

private
def print_hello
 puts "Hello everyone!"
end

end t = Test.new t.send( "print_hello" )

Output: Hello everyone!

Example -4 shows that it is possible to access private methods in Ruby through “send” function. Declaring as private is only a guideline in Ruby than a strict rule. There are workarounds to access those private methods. The advantage of such workarounds allows testing of private methods but it is a bad practice since private methods are internals of a class.

Since private methods have a loophole of security, alternative good practice would be to use accessor functions. In accessor functions, we implement the getter and setter methods for the private attributes, thereby providing the required security. The advantages of using accessor function are – Flexibility and Maintainability • Since the implementation is confined to the accessor functions, any future changes needs to be made at a single point. • Any type checking that needs to be done can be included within the accessor function. This prevents the object from getting into an inconsistent state.

In general, it is a good programming practice to use accessor functions instead of invoking private methods in Ruby.