Public, Protected and Private Methods in PHP vs. Ruby
Public Methods
Public methods are the most crucial methods in Object Oriented Programming. They expose the external signature of your class to other classes. In a Car for example, you as a driver can do things like “opening the door”, “starting the ignition”, or “turn the steering wheel”.
However, under the hood (pun intended) there’s a plethora of supporting actions that are not accessible by the driver. Things like “send electicity to spark plug”, “engage disc brakes”, etc. are the hidden methods to driving a car and are not part of the public interface.
In PHP, for each method we need to explictly define if the method is public, protected or private.
In Ruby, methods are public by default. You don’t need to specify they’re public, it’s assumed unless otherwise marked that all methods in a class are part of the class’s signature.
No need to define any kind of public
anywhere in a Ruby class, it’s just implict that unless a method is defined otherwise - then it’s a public method:
class Car
# Turn the steering wheel a certain direction
def turn_wheel(direction)
axel.turn(direction)
end
end
Using Private Methods
I’m going to go ahead and assume you’ve used some OOP in PHP in the past. One key concept is understanding “Private Methods”. This methods are used to organize logic internally inside of the Class.
The only difference between private methods and public methods, is that private methods are not accessible outside of the Object.
Private methods are not part of the Cat’s signature. A signature is just the available public methods on a particular object.
We have private method in Objects in Ruby as well. But they are defined a little differently:
class Cat
def walk
move_left_legs
sleep 1
move_right_legs
sleep 2
end
def run
move_left_legs
move_right_legs
def
private
def move_left_legs
# use your imagination here ok?
end
def move_right_legs
# yup, the right legs will move
end
end
cat = Cat.new
cat.stalk
cat.run
cat.move_left_legs
=> Cannot call 'move_left_legs'
Yup private methods are still a thing in Ruby.
In PHP, we have to explictly place the keyword private
in front of each method in a class:
However, Ruby’s take it on just requires you to set it once. Anything beneath the keyword private
becomes a private method:
private
def moveLeftLegs
# things happen here
end
def moveRightLegs
# things happen here
end
Protected Methods
Protected methods are essentially a step between a private and a public method. It’s still private in that an outside class cannot use the protected methods, but it’s accessible to other inheriting classes a.k.a. children.
Take this generic Car class for example:
Pretty simple, the external user a.k.a. Driver is able to insert a $key
into the ignition and 2 interior methods will do the actual work. If the checkKey
method fails, then the car doesn’t start.
Alrightly let’s implement our Car
class in Ruby:
class Car
def turn_ignition(key)
# using a combination of a guard statement + implict paranthesis around an argument
ignite_spark_plug if check_key key
end
protected
def ignite_spark_plug
car.ignite_spark_plug
end
private
def check_key(key)
key == slot
end
Again, much less typing required for the same result.
What if we had a car that had one of those fancy keyless entries? Technically we wouldn’t have to have a $key
inserted into the car, but we want to extend the class for similar functionality:
Now, this is a sneak peak into extending classes in Ruby, but you’re ready for a little taste:
class KeylessCar < Car
def turn_ignition
# using a combination of a guard statement + implict paranthesis around an argument
ignite_spark_plug if check_key
end
protected
def ignite_spark_plug
car.ignite_spark_plug
end
private
def check_key
key == slot
end
def super_secret_hash
# Car developers, please don't do this
'supersecretstringshhhh'
end
Where is $this
in Ruby?
So, I might have jumped ahead of myself in the last example. From inside of the Cat Class, we called the private method move_left_legs
and move_right_legs
, but we didn’t prepend this
. You’d expect to have to explictly tell Ruby to look for that method on the current Class.
Again, it’s optional you still can.
If you’d like to keep Ruby familiar as possible to what you already know. You can use the keyword self
to refer to the current Class. We can rewrite the run
method in our Cat
Class as such:
def run
self.move_left_legs
self.move_right_legs
def
That’s totally valid as well. However, don’t be surprised to see a lack of self
in Classes by other Rubyists. After awhile you just get used to the implict nature of the language.