POO en PHP

De Wiki Proyectos Beta
Ir a la navegación Ir a la búsqueda

Programación Orientada a Objetos

La programación orientada a objetos (POO, en español; OOP, en inglés) es un paradigma de programación que parte del concepto de "objetos" como base, los cuales contienen información en forma de campos (como atributos o propiedades) y sus respectivas acciones (métodos).

Los clases son capaces de interactuar y modificar los valores contenidos en sus campos o atributos (estado) a través de sus métodos (comportamiento).

Algunas características clave de la programación orientada a objetos son:

  • Herencia
  • Cohesión
  • Abstracción
  • Polimorfismo
  • Acoplamiento
  • Encapsulamiento.

Clases y objetos

Documentación oficial de clases y objetos: ES

Una clase comienza con la palabra reservada class, seguida de un nombre de clase, continuando con un par de llaves que encierran las definiciones de las propiedades y métodos pertenecientes a dicha clase.

El nombre de clase puede ser cualquier etiqueta válida, siempre que no sea una palabra reservada de PHP.

Observaciones

  • Un nombre válido de clase comienza con una letra o un guión bajo, seguido de una cantidad arbitraria de letras, números o guiones bajos.
  • Una clase puede tener sus propias constantes, variables (llamadas "propiedades") y funciones (llamados "métodos").
  • La variable $this está disponible cuando un método es invocado dentro del contexto de un objeto. $this es una referencia al objeto invocador.
  • Para crear una instancia de una clase, se debe emplear la palabra reservada new.
  • Las clases deberían ser definidas antes de la instanciación.

Si se emplea un string que contenga el nombre de una clase con new, se creará una nueva instancia de esa clase. Si la clase estuviera en un espacio de nombres, se debe utilizar su nombre completo al realizar esto.

Ejemplos

<?php
 class Auto {
   // Declaración de una propiedad
   public $color = 'blanco';
   
   // Declaración de un método
   public function getColor() {
       return $this->color;
   }
 }
 
 $auto1 = new Auto();
 $color = $auto1->getColor();
 echo "El auto es de color: " . $color;	// El auto es de color: blanco

Propiedades y métodos

Las propiedades y métodos de una clase viven en espacios de nombres diferentes, por tanto, es posible tener una propiedad y un método con el mismo nombre.

Al hacer referencia tanto a una propiedad como a un método se utiliza la misma notación, y si se accederá a la propiedad o se llamará al método, solamente depende del contexto.

Ejemplo

 <?php
  class Libro {
    public $title = 'Aprenda JavaScript - nivel principiantes';
    
    public function getTitle() {
      return 'Soy el metodo getTitle';
    }
  }
  
  $object = new Libro();
  echo $object->title;               // Aprenda JavaScript - nivel principiantes
  echo "   " . $object->getTitle();  // Soy el metodo getTitle

Modificadores public, private y protected

Uno de los principios de la programación orientada a objetos es la encapsulación, que es un proceso por el que se ocultan las características internas de un objeto a aquellos elementos que no tienen porque conocerla. Los modificadores de acceso sirven para indicar los permisos que tendrán otros objetos para acceder a sus métodos y propiedades.

Public

Es el nivel de acceso más permisivo que sirve para indicar que el método o atributo de la clase es público. En este caso se puede acceder a ese atributo, para visualizarlo o editarlo, por cualquier otro elemento de nuestro programa.

Ejemplo
class Persona { 
  public $nombre; 
   
  function __construct(){ 
    $this->nombre = "Proyectos Beta"; 
  } 
    
  public function saludar(){ 
    return "Me llamo" . $this->nombre; 
  } 
} 
 
$persona1 = new Persona(); 
$persona1->saludar();
 
echo "Soy: " . $persona1->nombre;

Private

Es el nivel de acceso más restrictivo que sirve que esa propiedad o método solo se va a poder acceder desde el propio objeto, y nunca desde afuera.

Observaciones
  • Si queremos acceder a una propiedad o método desde afuera del propio objeto, vamos a obtener un mensaje de error.
Ejemplo
class Persona { 
  private $nombre; 
   
  function __construct(){ 
    $this->nombre = "Proyectos Beta"; 
  } 
    
  private function saludar(){ 
    return "Me llamo" . $this->nombre; 
  }
  
  public function saludarATodos(){
      return $this->saludar();
  }
} 
 
$persona1 = new Persona(); 
$persona1->saludar();              // Error.

echo "Soy: " . $persona1->nombre;  // Error.
 
$persona1->saludarATodos();        // Funciona.

Protected

Es el nivel de acceso medio que sirve para que una propiedad o método sea publico dentro del propio objeto y cualquier clase que herede de él. Es privado y no accesible desde cualquier otra parte del objeto.

Constantes

Es posible definir valores constantes en función de cada clase manteniéndola invariable. Las constantes se diferencian de las variables comunes en que no utilizan el símbolo $ al declararlas o emplearlas. La visibilidad predeterminada de las constantes de clase es public.

Observaciones:

  • Las constantes de clase están asignadas una vez por clase, y no por cada instancia de la clase.

Ejemplos

Definición y uso de una constante
<?php
  class MiClase
  {
     const CONSTANTE = 'valor constante';
 
     function mostrarConstante() {
         echo self::CONSTANTE . "\n";
     }
  }
 
  echo MiClase::CONSTANTE . "\n";
 
  $nombreclase = "MiClase";
  echo $nombreclase::CONSTANTE . "\n"; // A partir de PHP 5.3.0
 
  $clase = new MiClase();
  $clase->mostrarConstante();
 
  echo $clase::CONSTANTE."\n"; // A partir de PHP 5.3.0
?>

Propiedades y métodos estáticos

Interfaces

Las interfaces de objetos permiten crear código con el cual especificar qué métodos deben ser implementados por una clase, sin tener que definir cómo estos métodos son manipulados.

Las interfaces se definen de la misma manera que una clase, aunque reemplazando la palabra reservada class por la palabra reservada interface y sin que ninguno de sus métodos tenga su contenido definido.

Documentación oficial de interfaces: ES

Observación

  • Todos los métodos declarados en una interfaz deben ser públicos, ya que ésta es la naturaleza de una interfaz.
  • Para implementar una interfaz, se utiliza el operador implements. Todos los métodos en una interfaz deben ser implementados dentro de la clase; el no cumplir con esta regla resultará en un error fatal. Las clases pueden implementar más de una interfaz si se deseara, separándolas cada una por una coma.

Ejemplos

Ejemplo 1

Ejemplo de interfaz

<?php
 // Declarar la interfaz 'iTemplate'
 interface iTemplate {
     public function setVariable($name, $var);
     public function getHtml($template);
 }

 // Implementar la interfaz
 class Template implements iTemplate {
     private $vars = array();

     public function setVariable($name, $var){
         $this->vars[$name] = $var;
     }

     public function getHtml($template){
         foreach($this->vars as $name => $value) {
             $template = str_replace('{' . $name . '}', $value, $template);
         }

         return $template;
     }
 }
Ejemplo 2

Interfaces extensibles.

 <?php
   interface a {
     public function foo();
   }

   interface b extends a {
     public function baz(Baz $baz);
   }

   class c implements b {
     public function foo() {}

     public function baz(Baz $baz) {}
   }

Namespaces

Los namespaces o espacios de nombres permiten crear aplicaciones complejas con mayor flexibilidad evitando problemas de conflictos entre clases y mejorando la legibilidad del código. Un namespace no es más que un directorio para clases, traits, interfaces, funciones y constantes. Se crean utilizando la palabra reservada namespace al principio del archivo, antes que cualquier otro código, a excepción de la estructura de control declare.

Documentación oficial de namespaces ES

Ejemplos

Ejemplo 1

Un archivo llamado MiClase.php

<?php
   // Directorio: Proyecto/Prueba/MiClase.php
   namespace Proyecto\Prueba;

   class MiClase {
       public function __construct(){
           echo "Hola, soy MiClase.";
       }
   }

Otro archivo llamado Test.php que utiliza el namespace Proyecto\Prueba;

<?php
 include_once ('MiClase.php');
 
 use Proyecto\Prueba\MiClase as miClase;

 $miClase = new miClase();

Type Hint

Desde PHP 5 es posible utilizar el type hinting (determinación de tipos) que permite especificar el tipo de datos que se espera de un argumento en la declaración de una función. Cuando se llama a la función, PHP comprobará si los argumentos son del tipo especificado, y si no lo son, se emitirá un error y la ejecución se detendrá.

Los tipos soportados son:

  • Arrays
  • Clases
  • Interfaces
  • Callables
  • Bool
  • Float
  • Int
  • Iterable
  • Object
  • Self
  • String
  • Void

Ejemplos

Ejemplo 1

class ChocolateAmargo {
    public $calorias = 520;
}

class Persona {
    public $energia;
   
    public function comerChocolateAmargo (ChocolateAmargo $chocolateAmargo) {
        $this->energia += $chocolateAmargo->calorias;
    }
    
    public function mostrarEnergia(){
        return "Energía actual: " . $this->energia . "<br/>";
    }
}

$josego = new Persona;
$desayuno = new ChocolateAmargo;
$josego->comerChocolateAmargo($desayuno);
$josego->comerChocolateAmargo($desayuno);
echo $josego->mostrarEnergia(); // Devuelve: Energía actual 1040

En el ejemplo, hemos forzado a que el argumento que se pasa a la función comerChocolateAmargo() sea un objeto de la clase ChocolateAmargo. Si el $desatuyno no fuera un objeto de la clase ChocolateAmargo, no se podría emplear la función comerChocolateAmargo() y arrojaría un error.

Ejemplo 2

class Persona {
   public $energiaMedia;
   public $comidas;

   public function calcularEnergia(array $comidas){
       $numeroComidas = count($comidas);
       $energiaTotal = $numeroComidas * $this->energiaMedia;

       return $energiaTotal;
   }
}

$josego = new Persona;

// Energía media que proporciona cada comida:
$josego->energiaMedia = 480;

// Total de comidas:
$comidas = array("Desayuno", "Almuerzo", "Comida", "Cena");

// Calcular la energía:
echo $josego->calcularEnergia($comidas); // Devuelve 1920

La función calcularEnergia() exige que el argumento sea un array. Si cambiamos el argumento y ponemos un integer, nos dará un error.

Excepciones