Confessions of a Converted PHP Developer: On Visibility and Privates

Share this article

Alright class—today I’m here to talk about the differences and similarities that PHP and Ruby have when it comes to object properties, methods, and their visibility—how you create variables inside classes, and how you can interact with them.

A Quick Recap of What We Know

In PHP, an object’s properties can be set to one of three visibilities; public, protected, and private. Properties that don’t have a visibility declaration default to public. Each of these declarations change what information is available to the class itself, its parents and children objects, and other code interacting with it. Let’s recap on how they work quickly.

  • Public variables are available everywhere
  • Protected variables are available only inside the class and its parents or children
  • Private variables are only available in the class where they are specified, and are not available to classes that extend it

To handle interactions with protected and private properties it’s common to create getter and setter accessor methods. These are functions that allow you to set and retrieve the values of properties, and generally all look pretty similar—unless they’re actually doing manipulation to the data that’s stored, it’s common to see them as just single line functions returning or setting the property:

<?PHP
&nbsp;
class animal
{
  private $_species;
  protected $_name;
&nbsp;
  public function get_species()
  {
    return $this->_species;
  }
&nbsp;
  public function get_name()
  {
    return $this->_name;
  }
}
&nbsp;
class pterodactyl
  extends animal
{
  public function __construct()
  {
    $this->_name = $name;
    $this->_species = 'dinosaur';
  }
}
&nbsp;
$my_big_birdie = new pterodactyl('Daryl');
&nbsp;
var_dump($my_big_birdie->get_name()); // string(5) 'Daryl'
var_dump($my_big_birdie->get_species()); // NULL

Calling the get_name method returns the name we set, since that variable was protected and available in the child class. By setting _species in the child class, it created a new public property called _species, and left the private _species property in the parent class NULL. A full dump of $my_big_birdie will show us this:

Object(pterodactyl)#1 (3) {
  ["_species":"animal":private]=> NULL
  ["_name":protected]=> string(5) "Daryl"
  ["_species"]=> string(8) "dinosaur"
}

Ruby doesn’t exactly have properties as we think of them. Instead you have to define getter and setter methods for any instance variables you want to access. These are commonly referred to as readers and writers. (Variables with an @ symbol in front of them are instance variables, which means that they’re available inside the scope of the class.)

class Animal
  def initialize(name)
    @name = name
  end
&nbsp;
  def name
    @name
  end
&nbsp;
  def name=(name)
    @name = name
  end
&nbsp;
  def species
    @species
  end
end

In this example we’ve implemented the animal class from PHP into Ruby. Note how the setter is defined by simply adding an equals to the end of the method name.

Since writing getters and setters can be a repetitive process, Ruby simplifies this by enabling us to declare which instance variables we want available as attributes:

class Animal
  attr_reader :species
  attr_accessor :name
&nbsp;
  def initialize(name)
    @name = name
  end
end

We now have the same class as before, except we’re creating our getters and setter with the Ruby attr_reader and attr_accessor. attr_reader creates only a getter method, attr_writer (unused here) only a setter method and attr_accessor creates both methods. 90% of the time this is all we need to do to expose our variables as attributes and for those times where you need more functionality, you can simply use the standard method construct.

Ruby also has a different implementation of Public, Private and Protected. By default all methods are public, but you can declare visibility by making a single protected or private statement and then any methods that follow will have that visibility. This allows you to group together methods with the same visibility:

class MyClass
  # the default visibility is public
  def my_public_method
  end
&nbsp;
  protected
  def my_protected_method
  end
&nbsp;
  def my_other_protected_method
  end
&nbsp;
  private
  def my_private_method
  end
end

Ruby’s implementation of protected and private is very different to PHP’s and has nothing at all to do with object inheritance. Private in Ruby is more akin to Protected in PHP. A private method in Ruby can be accessed inside the context of an object, or any inherited object.

class Foo
  private
  def bar
    puts "bar called"
  end
end
&nbsp;
class Blarg < Foo
  def initialize
    bar
  end
end

Because Blarg class extends Foo, it’s able to call the private method bar.

The implementation of protected in Ruby is different entirely to anything in PHP. Protected methods can be called by any object of the same class:

class Person
  attr_writer :mother
&nbsp;
  def initialize(name)
    @name = name
  end
&nbsp;
  def mother_name
    @mother.name if 
  end
&nbsp;
  protected
  def name
    @name
  end
end
&nbsp;
me = Person.new('Mal')
mum = Person.new('Jeni')
&nbsp;
me.mother = mum
&nbsp;
puts me.mother_name # => Jeni
puts me.name        # => NoMethodError: protected method `name' called for #

Here we have a person class that allows protected access to the name only. When I create two instances and set the mother attribute of one instance to the other instance, then the mother_name method is capable of calling the mother variable’s name attribute, however I’m not capable of calling the name attribute outside the scope of the object itself.

This was a brief overview of some of the fundamental differences between PHP and Ruby’s class properties and method visibility—can you think of any other core differences that are worth mentioning?

Mal CurtisMal Curtis
View Author

Mal Curtis is a Kiwi polyglot software engineer currently focussing on Go and JavaScript. He’s the founder of transaction email management service Apostle.io, and is a Principal Engineer at Vend, where he helps make beautiful Point of Sale and Inventory Management software (yes, it can be beautiful). In the past he’s helped launch Learnable.com, and worked for SitePoint in Melbourne. In his spare time you’ll find him attempting geeky pursuits with varying levels of failure, such as quadcopters and sous vide cooking.

PHPprivatepublicrubyvisibility
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week