Está en la página 1de 20

Practícalo: Clases y Objetos de PHP

Noviembre 2023
Tammy Robison

Introducción
1. Conviértase en un exitoso desarrollador de PHP

En la industria actual, para ser un desarrollador PHP exitoso, debe ser un programador
orientado a objetos competente. Los frameworks PHP populares como Drupal, Symfony y
Laravel utilizan patrones de diseño orientados a objetos. En este curso, podrá evaluar su
conocimiento de conceptos fundamentales orientados a objetos como clases, objetos y
herencia a través de una serie de desafíos integrales. Soy Tammy Robinson, y he sido
desarrolladora profesional de PHP y organizadora de la comunidad tecnológica durante
los últimos ocho años. Únase a mí mientras revisamos estos conceptos y probamos sus
habilidades aplicándolos a un caso de uso del mundo real en el camino.

2. Lo que deberías saber

Para sacar el máximo provecho de este curso, usted debe ser capaz de leer y entender
un programa escrito en PHP. También debe comprender los conceptos básicos de PHP,
como imprimir declaraciones, escribir funciones y almacenar datos y variables. Si algo de
esto le suena desconocido, tómese un momento para ver el curso de capacitación
esencial de PHP en esta biblioteca. Este curso le ayudará a evaluar su conocimiento de la
programación orientada a objetos en PHP. Cubriremos rápidamente una serie de temas y
haremos un seguimiento de cada video con un breve desafío para que pruebes por tu
cuenta. Cada desafío tiene un video de solución que puede usar para verificar su código o
usar como referencia en caso de que se quede atascado. El cuestionario de evaluación
previa lo ayudará a determinar qué temas ya le son familiares. Si lo haces bien en esas
preguntas, siéntete libre de saltar directamente a los desafíos del código. Para seguir este
curso, necesitarás tener una cuenta de GitHub, ya que usaremos GitHub Codespaces
para trabajar dentro del editor de código VS Code en el navegador. Para presentarte
GitHub Codespaces aquí está el instructor Senior Staff, Ray Villalobos. Nos vemos en el
próximo video.

3. Uso de GitHub Codespaces con este curso

Este es Ray Villalobos, instructor senior de LinkedIn Learning, y te mostraré cómo trabajar
con los cursos de LinkedIn Learning usando GitHub Codespaces. Codespaces es un
editor de código en la nube con toda la potencia de Visual Studio Code.

Permite la práctica práctica en el mundo real que refleja el desarrollo de software en el


lugar de trabajo. Este curso fue creado usando GitHub Codespaces. Con Codespaces,
tiene todo lo que necesita para ponerse en marcha sin necesidad de instalaciones
complejas o herramientas de compilación.
Un clic y estás listo para comenzar. Para practicar junto con el curso, puede crear un
espacio de código directamente desde la página de descripción general del curso.
Primero, haz clic en abrir junto a GitHub Codespaces. Si ya has iniciado sesión, se te
dirigirá a una página de introducción a GitHub Codespaces. Si no has iniciado sesión, se
te pedirá que inicies sesión o que primero crees una cuenta gratuita de GitHub.

Desde esta página, haga clic en crear codespace en main. La primera vez que abra un
espacio de código, puede tardar unos minutos en crear la máquina virtual. Una vez hecho
esto, ingresará al entorno del editor de código. Si está familiarizado con Visual Studio
Code, esta es una versión especial de ese editor que se ejecuta en los servidores de
GitHub.

Su curso puede tener una o más extensiones preinstaladas según el curso que esté
tomando. Estos se pueden encontrar en el panel de extensiones. Debido a que este es un
navegador, es fácil cerrar inadvertidamente la ventana del navegador y perder el editor. Si
haces eso, no entres en pánico. Codespaces guarda todo lo que está haciendo en una
máquina virtual. Siempre puede recuperar el espacio de código para este repositorio aquí
mismo.

Observe que incluso recordó que había abierto el panel de extensiones. Una forma
alternativa de crear un espacio de código es directamente desde uno de los repositorios
de GitHub de nuestro curso. Desde aquí, haga clic en código y luego cree codespace en
main. También puede reiniciar un espacio de código anterior desde esta ubicación.

GitHub Codespaces es compatible con dispositivos con tamaños de pantalla más


pequeños como teléfonos móviles o tabletas, pero está optimizado para pantallas más
grandes, por lo que le recomendamos que practique junto con este curso en una
computadora portátil o de escritorio.

El curso de ejemplo que estoy viendo es lo que se conoce como un repositorio de


sucursal plana. Se puede decir porque hay una sola rama cuando hace clic en el icono de
la rama en la barra de estado. También se puede decir porque hay diferentes carpetas
para cada uno de los videos en el curso.

Esta es una muestra de cómo se ve un repositorio de varias sucursales, que es más


común cuando se trabaja con marcos web. Si va al icono de la rama en la barra de
estado, puede ver que hay más de una rama. Puede cambiar a las diferentes ramas
utilizando este menú.

Las ramas se nombran con el capítulo y el número de video que está viendo. Si ves una B
al final de la rama, así es como se veía el código al principio. Si ves una E, así es como se
veía el código al final. Cambiemos a cómo se veía el código en el capítulo dos y el tercer
video.

Elegiré la rama inicial. A medida que avanza en un curso, puede realizar algunos cambios
en una rama. Voy a hacer una edición menor en el archivo .html índice aquí mismo. Voy a
seguir adelante y guardar eso, y pueden ver que he modificado este archivo porque hay
una M aquí y el nombre de la rama ahora tiene un asterisco.

Si intento cambiar a otra rama que causa cambios importantes como, por ejemplo,
07_03e, puedo ver un cuadro de diálogo como este.
Si no le importa guardar sus cambios, simplemente puede presionar el botón de pago
forzado. Te permitirá cambiar a esa rama. A continuación, puede optar por descartar los
cambios en este archivo.

Su instructor le informará cuál es la estructura de carpetas para su curso. Biking le


permite crear su propia copia del repositorio en su cuenta para que pueda conservar los
cambios que haya realizado, incluso si ha eliminado el espacio de código.

Para crear su propia bifurcación, puede hacer clic en el botón de bifurcación en el


repositorio. Voy a presionar crear tenedor. Tendré mi propia copia de este repositorio, y si
quiero, puedo iniciar un nuevo espacio de código en esa bifurcación.

Esta versión bifurcada es casi exactamente igual que el repositorio original, pero le
permitirá impulsar sus propios cambios. Observe que la URL del repositorio es
ligeramente diferente.

Sigamos adelante y hagamos un simple cambio en este archivo aquí mismo. Voy a
guardarlo. Notará que hay una M aquí, así como un asterisco en esta rama. En el panel
de control de código fuente, también puede ver uno para el cambio que acabamos de
hacer. Sigamos adelante y tratemos de comprometer este cambio.

Voy a presionar el botón de confirmación y le pediré que siga adelante y organice los
cambios. Y luego voy a presionar este botón aquí. Voy a golpear bien. También puede
dejar que siga adelante y ejecutar git fetch. De esa manera, se sincronizará
automáticamente con su repositorio bifurcado. Ahora ese cambio se almacenará en su
propia versión de este repositorio.

No se preocupe si olvida bifurcar un repositorio y luego intenta impulsar los cambios.


Codespaces también le preguntará si desea crear una bifurcación automáticamente.
Busque consejos adicionales específicos del curso del instructor. Ahora, volvamos al
curso.

1. Objetos y Clases
1.1. Definiciones de clase

En programación orientada a objetos organizamos el diseño de nuestra aplicación en


torno a estructuras de datos llamadas objetos. Estos objetos son instancias únicas de una
clase, que es una plantilla que define las propiedades y los métodos de los objetos que
tiene. Este video cubrirá cómo se define una clase. Puede definir una clase de dos
maneras. Puede ser una clase con nombre o una clase anónima. Para definir una clase
con nombre, comience con la palabra clave class seguida del nombre de la clase. Luego
incluya un par de tirantes rizados para encerrar el cuerpo de la clase. Una clase anónima
comenzará con la palabra clave new and class, seguida del cuerpo de la clase. Estos son
los más adecuados para las clases que solo tiene la intención de usar una vez en su
aplicación. Hay tres grupos diferentes de datos que podemos agregar a una definición de
clase. Los datos de instancia incluyen las propiedades y los métodos que pertenecen a un
objeto. Una propiedad de instancia es una variable que representa una característica
única de un objeto, mientras que los métodos de instancia son funciones que exponen los
comportamientos del objeto. Este es un ejemplo de una clase de automóvil que declara
tres propiedades de instancia: color, tipo de carrocería y arranque del motor. También
incluye un método de instancia única llamado unidad. Cada propiedad de instancia tiene
un modificador de acceso y una declaración de tipo antes de su nombre. Si es necesario,
puede proporcionar un valor predeterminado para una propiedad en el momento en que
se declara. El método de instancia también comienza con un modificador de acceso. Este
método en particular espera recibir un booleano como argumento en el momento en que
se llama. Si los modificadores de acceso no le resultan familiares, no se preocupe por
eso. Los revisaremos con más detalle más adelante, en el Capítulo 2 de este curso. A
continuación, tenemos datos estáticos. Los datos estáticos incluyen propiedades y
métodos enlazados a una clase en lugar de a una sola instancia. Esto significa que no se
requiere un objeto de la clase para que pueda usarlos, y se debe acceder a ellos
utilizando la propia clase. Las declaraciones para propiedades y métodos estáticos son
similares a lo que acabamos de ver, por ejemplo, datos, excepto que incluyen una palabra
clave estática en su definición. La palabra clave estática es lo que une estas propiedades
y métodos a la clase. Finalmente, tenemos constantes. Las constantes se utilizan para
definir variables cuyos valores aparecen en varios lugares a lo largo de una clase y, una
vez asignados, sus valores no cambian. Para agregar una constante a una clase, use la
palabra clave const seguida de un nombre y el valor que desea asignar. Usando el mismo
ejemplo de clase, usamos una constante para definir la unidad de velocidad para un
automóvil en millas por hora. Si esto alguna vez necesita cambiar, simplemente
actualizamos el valor de la variable constante sin necesidad de cambiar ninguna otra
parte del código. Observe que el nombre constante tiene todas las letras mayúsculas y
usa guiones bajos para separar cada palabra. Esto completará nuestra revisión sobre
cómo crear clases. Sigamos adelante y saltemos a nuestro primer ejercicio.

1.2. Pruébelo: Definición de una clase

Es hora de su primer ejercicio Pruébelo. Para este ejercicio usarás lo que acabas de
aprender para definir un conjunto de clases para una aplicación de mensajería ficticia
llamada Flack. La aplicación tendrá un área de trabajo, un chat, un miembro y una clase
de mensaje. Además de crear estas clases, su desafío será determinar si las propiedades
y los métodos agregados a cada clase deben ser datos constantes, de instancia o
estáticos, en función de lo siguiente. Todos los miembros deben poder crear nuevos chats
dentro de un espacio de trabajo y enviarles mensajes. Si un miembro tiene un rol de
administrador, debería poder crear un espacio de trabajo y agregar miembros del espacio
de trabajo. Los espacios de trabajo deben realizar un seguimiento de sus miembros y sus
chats. También deben tener una URL única que termine con un nombre de dominio
flack.app. Los chats solo deben tener una propiedad de título y mensajes. Y por último,
pero no menos importante, además de su contenido, los mensajes deben incluir una
propiedad de autor y una marca de fecha y hora que indique cuándo se publicó el
mensaje. Por ahora, todas las propiedades y métodos que declare deben tener un
modificador de acceso público y deben incluir declaraciones de tipo cuando sea
necesario. No espero que sus métodos tengan ninguna lógica en este momento, por lo
que está bien si solo incluye sus firmas y un cuerpo vacío. Para comenzar, consulte la
rama del repositorio de GitHub titulada 01_03B. Notarás algunos archivos diferentes que
ya existen, así que repasaré rápidamente los que trabajarás. La carpeta de origen
contiene un conjunto de archivos de clase vacíos y un archivo .php aplicación. El
archivo .php aplicación servirá como punto de entrada a su aplicación. También verá una
carpeta de configuración que contiene algunos archivos auxiliares. No tendrá que
preocuparse por hacer cambios en estos. Se pusieron en marcha para facilitar el trabajo a
través de los ejercicios. El archivo helper.php tiene una función auxiliar que puede utilizar
en los ejercicios para imprimir datos en el terminal. Ingresará automáticamente una nueva
línea entre cada declaración impresa, por lo que no tiene que hacerlo manualmente.
Autoload.php cargará automáticamente los archivos de clase para que no tenga que
escribir una instrucción include para cada clase en cada archivo en el que trabaje. Eso es
todo por ahora. Si te quedas atascado, salta al siguiente video para ver mi solución.
¡Buena suerte!

1.3. Compruébalo: Definiendo una clase

Muy bien. Bienvenido al primer video de solución para este curso. Te guiaré a través de
cómo creé las clases que usaremos para nuestra aplicación de mensajería Flack. Antes
de comenzar, quería señalar el archivo README de desafío en el archivo explorar el
archivo de la izquierda. Entonces, si haces doble clic en challenge.md, verás que he
esbozado el objetivo, la lógica del programa, así como los requisitos que se necesitan
para que completes este desafío. Incluiré uno de estos archivos para cada desafío en
caso de que necesite una referencia rápida de lo que requiere el programa. Así que
entrando directamente en el código de la solución, voy a comenzar con nuestra clase de
miembros. Ahora, si recuerda correctamente del video de descripción general que
conocemos para declarar una clase en PHP, comenzamos con la palabra clave de clase,
seguida del nombre de la clase y llaves para el cuerpo de la clase. Dentro de mi clase,
voy a agregar dos variables que contienen los valores de los diferentes roles que puede
tener un miembro, que es admin o miembro. Voy a agregar estos valores como variables
constantes. Así que comenzaré con la palabra clave constante seguida del nombre de la
variable, y luego le asignaré el valor que quería tener. Repetiré esto en otra línea para
nuestro rol predeterminado y le daré un valor de miembro. Así que ahora tenemos
nuestros roles de administrador y miembro. Ahora, decidí usar estas variables constantes
por dos razones. Uno, estos valores no deben cambiar a lo largo de nuestro código, y
luego también tendré una variable consistente que puedo usar cuando necesite hacer
referencia a estos roles. Ahora, si por alguna razón quisiera actualizar estos valores,
podría cambiar las cadenas en línea cinco y seis y el resto de mi código seguirá
funcionando de la manera que espero. A continuación, voy a agregar las propiedades de
inscripción de nombre de usuario. Entonces, para agregar esas propiedades,
comenzaremos con el modificador de acceso, seguido de la declaración de tipo y el
nombre de la propiedad. Volveré a hacer esto en la línea nueve para nuestra propiedad
de rol. Ahora, ninguna de estas propiedades necesita tener un valor inicial. Para el
nombre de usuario en particular, no queremos inicializarlo porque debe ser único para
cada objeto miembro que creamos. Finalmente, solo tenemos que agregar los métodos
que esta clase necesita. Por lo tanto, sabemos que cada miembro debería poder crear un
chat, crear un espacio de trabajo, agregar un miembro del espacio de trabajo y publicar
mensajes en un chat. Entonces, primero, agregaré nuestro método de agregar miembro
del área de trabajo. Y para hacer eso, comenzaré con nuestro modificador de acceso
público seguido de la palabra clave function y el nombre del método, que es agregar
miembro del espacio de trabajo. Muy bien, y de nuevo, nuestros miembros deberían tener
la capacidad de crear un chat. A continuación, deberían poder crear un espacio de
trabajo. Y finalmente, agregaremos un método para publicar un mensaje en un chat.
Ahora, esto prácticamente completa todo lo que necesitamos para nuestra clase de
miembros. Tenemos nuestros roles descritos en las líneas cinco y seis. Tenemos
propiedades para nombre de usuario y rol, y luego tenemos todos los métodos que
describen los comportamientos que debe tener un objeto miembro. Para completar este
desafío, básicamente repetiré estos mismos pasos para las clases restantes. Entonces,
desde la pestaña de archivos en la parte superior, pasaré a la clase de espacio de trabajo.
Ahora ya tengo la clase definida, así que todo lo que necesito hacer aquí es agregar los
datos. Así que comenzaré agregando una variable de cadena para nuestra URL. Luego
agregaré una matriz para los chats del espacio de trabajo. También voy a inicializar esto
en una matriz vacía, ya que va a contener una colección de elementos. Luego haré lo
mismo en línea siete para la propiedad de un miembro. Ahora, para cada espacio de
trabajo que se crea, debe tener una URL que termine con el nombre de dominio flack.app
según los requisitos. Y como este valor es el mismo para todos los objetos de espacio de
trabajo que creamos, agregaré este valor a la clase como una propiedad estática. Así que
en la línea nueve, comenzaré con nuestro modificador de acceso seguido de la palabra
clave estática. Luego, por supuesto, le daré una declaración de tipo y luego un nombre. Y
eso prácticamente completa la clase de espacio de trabajo. Ahora, para nuestra clase de
chat, todo lo que necesitamos es un título y una propiedad de mensajes. Así que
comenzaré con la cadena para el título, y luego otra matriz para los mensajes. Y
finalmente, en la clase de mensaje tendremos tres cadenas aquí para el contenido, el
autor y la fecha. Así que comenzaré agregando una cadena para el contenido, otra para el
autor y, finalmente, una cadena para la fecha. Ahora, esto prácticamente completa este
desafío. Esperaría que su código sea similar al que tengo aquí en cuanto a sus opciones
entre datos instantáneos, estáticos y constantes. Si desea echar un vistazo más de cerca
a esta solución, mire la rama cero uno subrayado cero tres E del repositorio en GitHub. Si
siente que hubo una gran diferencia entre lo que tengo aquí y lo que hizo en su solución,
tómese un momento para volver a visitar el video de descripción general antes de pasar al
siguiente tema.

1.4. Crear instancias de clase

Ahora que hemos visto cómo definir una plantilla de objetos usando una clase, echemos
un vistazo a cómo usamos realmente una clase para crear un objeto. Podemos crear
objetos únicos asignando una variable a una clase anónima. La definición de clase debe
actualizarse con cualquier propiedad o método que necesitemos del objeto. Aquí hay otro
vistazo a nuestro ejemplo de clase de automóvil del video anterior. Para crear un nuevo
objeto a partir de una clase con nombre, declaramos una variable, luego instanciamos la
clase, colocando la nueva palabra clave justo antes del nombre de la clase. Podemos
continuar haciendo múltiples instancias de nuestra clase de automóvil repitiendo estos
mismos pasos. Si bien el comportamiento de ambos objetos será el mismo, podemos
inicializar cada una de nuestras propiedades de objetos con un conjunto de sus propios
valores únicos. PHP proporciona un puñado de funciones integradas para trabajar con
clases y objetos. Aquí voy a destacar la función get_class, ya que puede ser útil para
usted cuando esté trabajando en sus próximos ejercicios. Para obtener el nombre de una
clase de la que un objeto es una instancia, podemos usar la función get_class pasando el
objeto que queremos probar. Si omitimos el parámetro object al usar esta función dentro
de una clase, el nombre de la clase se devolverá en su lugar. Si intenta utilizar esta
función fuera de una clase sin pasar explícitamente un objeto, el código producirá un
error. Para obtener una lista completa de las funciones auxiliares de clases y objetos,
puede visitar la documentación de referencia oficial de PHP en php.net.

1.5. Pruébelo: crear un objeto

Ahora que tus clases están definidas, es hora de usarlas para practicar la creación de
objetos. Para este ejercicio, creará un nuevo objeto para cada clase dentro del
archivo .php aplicación principal. Después de crear los objetos, siéntase libre de
experimentar imprimiéndolos en el terminal para examinar su salida. También puede
utilizar la función get_declared_classes para comprobar que las clases se han declarado
correctamente. Si lo han hecho, aparecerán en la salida que devuelve la función. Para
ejecutar el archivo principal de la aplicación, asegúrese de que su terminal esté
configurado en la raíz de la carpeta de origen. A continuación, escriba el comando que ve
aquí.

1.6. Compruébalo: Creando un objeto

Para este desafío, se le pidió que creara una nueva instancia de objeto de cada clase y
que examinara esos objetos dentro del terminal. Primero abriré el archivo principal de la
aplicación desde la vista del Explorador expandiendo nuestra carpeta de origen y
haciendo doble clic en la aplicación.php. En una nueva línea comenzaré a crear un nuevo
objeto para cada clase. Así que primero, crearé un nuevo objeto miembro. Crearé una
variable para contener el objeto y luego, para instanciarlo, usaré la nueva palabra clave
seguida de la clase a partir de la cual quiero crear el objeto. Ahora, haré esto para
nuestras clases restantes repitiendo este mismo proceso. Así que aquí tenemos un nuevo
objeto de espacio de trabajo, en la línea siete, crearé un nuevo objeto de chat y luego,
finalmente, tendremos un nuevo objeto de mensaje. Y para verificar que estas clases se
han declarado correctamente y que nuestros objetos son buenos, imprimiré el resultado
de la función PHP get_declared_classes usando nuestro ecoayudante. Así que hagamos
una llamada a esa función de ayudante en la línea 10. Y luego dentro de esto podemos
pasar una llamada para obtener clases declaradas. Ahora, antes de poder ver esta salida,
tendré que abrir el terminal. Y para hacer eso, podemos ir al menú de hamburguesas aquí
en el extremo izquierdo, bajar a Ver y luego hacer clic en la opción Terminal. Muy bien. De
forma predeterminada, el terminal se establecerá en la raíz del proyecto. Pero
necesitamos estar dentro de la carpeta de origen para ejecutar nuestro archivo de
aplicación. Así que cambiemos los directorios a la carpeta de origen y luego, una vez que
estemos allí, podemos ejecutar nuestro comando de archivo de aplicación. Ahora que
está impreso, voy a ampliar un poco este terminal para que podamos ver más de la salida.
Y aquí abajo, en la parte inferior, pueden ver que he resaltado nuestras cuatro clases, así
que eso es genial. Ahora sabemos que han sido declarados correctamente. Los otros
elementos que ves son solo clases que están integradas en PHP. Así que estos estarán
allí sin importar qué sea cada vez que use esa función. Muy bien, sigamos adelante y
aclaremos esto escribiendo el comando borrar y luego presionando Enter. Luego
arrastraré la ventana del terminal hacia abajo, para que podamos ver nuestro código
nuevamente. Ahora, para inspeccionar los objetos un poco más de cerca, voy a imprimir
el objeto de espacio de trabajo como ejemplo. Pero antes de hacer eso, vamos a
comentar la línea 10 para que cuando imprimamos esto tengamos un poco más de
espacio para trabajar dentro de la terminal. Muy bien, debajo de eso llamemos a nuestra
función de ayudante nuevamente y luego pasemos un objeto de su elección. Muy bien, de
vuelta en el terminal volveremos a llamar a nuestro comando. Y luego puede ver que
nuestro objeto de espacio de trabajo no se ha impreso. Ahora, dependiendo de la función
de impresión que utilice, el contenido que ve en la salida será un poco diferente. Pero si
está utilizando nuestra función de ayuda, debería ver lo mismo que estoy viendo aquí.
Ahora, examinando el objeto un poco más de cerca, puede ver que imprimió cada una de
las propiedades que agregamos a nuestra clase en el video anterior. Tenemos nuestra
propiedad URL, la propiedad de un chat y luego la propiedad de un miembro. Ahora, lo
único que nos falta es la propiedad de dominio URL. Esa propiedad en particular no se
imprimiría aquí porque esa propiedad pertenece a la clase. Es una propiedad estática.
Estamos imprimiendo un objeto aquí, por lo que cada propiedad que se imprime aquí es
una propiedad de instancia. Ahora, esto también nos dice si nuestras propiedades se
inicializaron o no con el valor cuando se crearon. Así que nuestra propiedad url que
podemos ver no estaba inicializada, pero que tiene una cadena de tipo. Los chats y los
miembros, por otro lado, se muestran como matrices y luego también muestran el valor
inicial de esas matrices. Eso es más o menos todo para este. Ahora que tenemos lo
básico, podemos pasar a agregar alguna funcionalidad a nuestra aplicación.

2. Trabajar con datos de objetos y clases


2.1. Operadores y modificadores de acceso

En el capítulo anterior cubrimos cómo crear clases y objetos y discutimos los tipos de
datos que les pertenecen. Ahora tendremos una visión más detallada de cómo usar las
propiedades y métodos que agregamos a una clase y cómo los modificadores de acceso
juegan un papel en esto. Para acceder a una propiedad de objetos o invocar uno de sus
métodos fuera de la clase, encadenamos el operador de objeto de la variable del objeto
seguido del nombre de la propiedad o método. El acceso a los datos de instancia dentro
de la clase es ligeramente diferente. En lugar de crear una variable nosotros mismos para
representar el objeto, se nos da una referencia al objeto actual a través de una pseudo-
variable incorporada llamada esto. Cuando el segundo objeto se realiza utilizando la
misma clase, el valor de la pseudovariable cambia a este nuevo objeto en el momento en
que se llama a su propiedad o método. También podemos usar nuestra pseudo variable
para implementar una técnica llamada método de encadenamiento. El encadenamiento de
métodos nos permite hacer llamadas a los métodos de un objeto usando una sola
instrucción. Para incluir un método en una cadena de métodos, la instrucción final de su
cuerpo debe devolver la referencia de la instancia de objeto actual. No se puede acceder
a las propiedades y métodos estáticos mediante el operador de objeto, ya que no son
relevantes en el contexto de un objeto. En su lugar, usamos un operador de resolución de
ámbito representado por dos puntos dobles para acceder a ellos directamente en la propia
clase. Para evitar errores en su código, al realizar una llamada a una propiedad estática,
asegúrese de incluir el signo de dólar inicial en su nombre. Similar a tener una referencia
al objeto actual dentro de una clase, una referencia a la clase actual dentro de su
definición se realiza utilizando la palabra clave self. Podemos cambiar la accesibilidad de
todas las propiedades y métodos de una clase mediante uno de los tres modificadores de
acceso. Un modificador público significa que podemos acceder a la propiedad o método
en cualquier lugar dentro de nuestro código. Esta es la visibilidad predeterminada
asignada a una propiedad o método cuando no se especifica ninguna. Privado significa
que solo podemos acceder a la propiedad o método dentro de la clase en la que se creó.
Un modificador de acceso protegido funciona igual que uno privado, excepto que la clase
secundaria también puede acceder a cualquier propiedad y método protegido desde su
padre. Cubriremos los detalles de una relación de clase de padre a hijo más de cerca en
el próximo capítulo. Las propiedades privadas y protegidas ayudan a encapsular los datos
a los que otras partes del programa deben tener acceso restringido. Si aún necesita usar
el valor de una de estas propiedades, puede hacerlo agregando un método público getter
y setter a su clase. El método setter debe actualizar el valor de la propiedad, mientras que
el método getter debe devolver su valor actual. También puede usar el método getter para
cambiar el formato del valor de una propiedad antes de que finalmente se devuelva.

2.2. Pruébelo: inicialice los datos y el comportamiento del objeto

Ahora que sabe cómo acceder a los datos de clases y objetos, es hora de dar vida a
nuestra aplicación. Para este próximo desafío, practicará la asignación de valores a las
propiedades de sus objetos y escribirá la implementación de sus métodos. En el archivo
principal de la aplicación, deberá crear dos nuevos objetos miembro y asegurarse de que
uno sea un administrador. A continuación, utilice admin para crear un nuevo espacio de
trabajo y agregue el objeto no admin como uno de los miembros de los espacios de
trabajo. A continuación, puede utilizar cualquiera de sus miembros para crear un nuevo
chat dentro del espacio de trabajo y publicar un mensaje. Para verificar que su programa
funciona, imprima la URL de los espacios de trabajo, sus miembros y los mensajes de
chat en su terminal. Aquí hay algunos consejos adicionales para ayudar con su código. Un
administrador solo puede agregar un miembro a un espacio de trabajo, por lo que no
deberíamos poder establecer un miembro utilizando el objeto de espacio de trabajo
directamente. Además, un miembro solo puede crear chats para un espacio de trabajo al
que pertenece. A medida que avanza en este desafío y los otros que seguirán, piense si
tiene sentido actualizar la visibilidad o el valor inicial de cualquier propiedad existente en
función de los requisitos del programa.

2.3. Compruébelo: inicialice los datos y el comportamiento del objeto

Bienvenido de nuevo. Espero que hayas podido superar este desafío. Hay muchas
maneras de implementar la lógica para este, por lo que es muy posible que mi solución
sea diferente de la forma en que decidiste hacer las cosas. Pero te guiaré a través del mío
paso a paso para que puedas ver cómo conecté las cosas. Comencemos con el archivo
principal de la aplicación. Así que en las líneas cinco y siete, he creado dos objetos
miembro, uno administrador y otro no administrador. Los usaré para crear un nuevo
espacio de trabajo, agregarle un chat y luego publicar algunos mensajes. Por lo tanto, el
primer paso para completar este desafío es inicializar las propiedades de los objetos
miembro. Entonces, debajo de mi administrador, seguiré adelante y accederé a su
nombre de usuario usando el operador de objeto, y luego le daré un nombre de usuario de
acme_admin. Haré lo mismo para el no administrador, accediendo a su nombre de
usuario, y luego le daré un nombre de usuario de acme_member. Ahora, una de las
actualizaciones que hice a la clase miembro aquí en la línea nueve fue inicializar la
propiedad de rol con el rol de miembro predeterminado. Por lo tanto, cuando mis objetos
se vuelven a crear en el archivo principal de la aplicación, sus roles se establecen
automáticamente. Ahora que eso está hecho, el siguiente paso es crear un espacio de
trabajo y agregar ambos miembros. Así que veamos lo que están haciendo esos métodos.
Me desplazaré hacia abajo aquí para crear un espacio de trabajo, y luego abriré ese
método, para que podamos ver su contenido. Por lo tanto, el método create workspace
acepta un subdominio como parámetro aquí. Ahora, el subdominio se utiliza para
establecer la URL del espacio de trabajo. Como verá dentro del método, creo un nuevo
objeto de espacio de trabajo y luego establezco la URL en la línea 40, y en la línea 41,
establezco el administrador del espacio de trabajo en el objeto miembro actual y,
finalmente, devuelvo el espacio de trabajo. Podría haber tenido fácilmente la lógica para
establecer URL y establecer admin dentro de este método de creación de espacio de
trabajo, pero como esas dos acciones son muy específicas del objeto de espacio de
trabajo, decidí moverlo a la clase de espacio de trabajo. Así que tomemos un desvío
rápido al espacio de trabajo.php y le mostraré lo que hacen estos métodos. Ahora
establezca la URL, toma un subdominio como parámetro y luego lo combina con la
propiedad de dominio URL para establecer la URL del espacio de trabajo. Luego, en la
línea 16, el método set admin establece el rol de administrador en el pase del objeto
miembro y, a continuación, agrega ese miembro al área de trabajo. Ahora, como he
establecido métodos Url tanto para el administrador como para la URL, seguí adelante y
agregué métodos getUrl para ellos también. Entonces, getURL simplemente devuelve el
valor de la propiedad URL del espacio de trabajo, y luego dentro de getAdmin, hago una
búsqueda de filtro en la matriz de miembros del espacio de trabajo para encontrar el que
tiene un rol de administrador. Ahora, si esa búsqueda vuelve vacía, simplemente
devolveré false de este método. De lo contrario, devuelvo el primer elemento del
resultado. Lo último que hice aquí, fue actualizar la propiedad URL en la línea 5, le di un
modificador de acceso privado. De este modo, la dirección URL del área de trabajo no se
puede establecer utilizando esa propiedad directamente. Eso explica todo lo que sucede
cuando se crea un nuevo espacio de trabajo. Así que ahora explicaré rápidamente la
adición de un nuevo miembro. Así que desplácese un poco hacia arriba y luego abramos
este método. Así que este método tomará dos parámetros. Toma el miembro que
queremos agregar al espacio de trabajo, y el segundo parámetro es el espacio de trabajo
al que se debe agregar el miembro. Y en realidad colapsaré nuestra vista de explorador
aquí, para que podamos ver lo que está sucediendo un poco mejor. Para hacer eso,
simplemente haré clic en este elemento resaltado, y eso debería cerrar el explorador por
usted. Muy bien. Ahora, dentro del método, aquí en la línea 13, estoy agarrando el
administrador del espacio de trabajo, para poder verificar si el administrador del espacio
de trabajo coincide con el miembro que está intentando agregar este nuevo miembro.
Ahora, si se aprueba el cheque, en la línea 20, agregaré ese miembro al espacio de
trabajo. Con todo eso en mente, volvamos al archivo principal de la aplicación y usemos
estos métodos. Así que lo primero que haré es crear un nuevo espacio de trabajo usando
el administrador. Así que tengo el objeto admin aquí, y luego llamaré crear espacio de
trabajo, y luego le daré un subdominio de acme. Y debajo de eso, usaré el administrador
para agregar un nuevo miembro del espacio de trabajo. Lo pasaré a nuestro miembro no
administrador, y luego le pasaré el espacio de trabajo que acabamos de crear en la línea
11 como segundo parámetro. Ahora, para verificar que todo esto funciona, imprimiré la
URL del espacio de trabajo y los miembros. Así que usaré nuestro ayudante aquí, y luego
usaré el objeto workspace para obtener su URL, y luego lo haré nuevamente en la línea
15 para obtener los miembros del workspace. Ahora para abrir el terminal para que
podamos ejecutar este archivo, vamos al menú hamburguesa, bajamos a ver, y luego
hacemos clic en la opción de terminal. Ahora voy a expandir completamente este panel
para que podamos ver mejor la salida. Para hacer eso, simplemente haga clic en la
pequeña flecha aquí, y maximizará el panel para usted. Ahora, quiero asegurarme de que
ya estoy en el directorio de origen, así que permítanme enumerar los archivos
rápidamente. Muy bien, se ve bien. Así que borraré esto y luego ejecutaré el archivo
principal de la aplicación. Bien. Como puede ver, tenemos nuestra URL de espacio de
trabajo de acme.flack.app, y también tenemos nuestra matriz de miembros impresa. El
primer miembro es nuestro objeto admin, y luego el segundo es nuestro non admin acme
member. Ahora, también puedo hacer una comprobación rápida para asegurarme de que
la aplicación fallará correctamente si no hay un administrador configurado en el espacio
de trabajo. Así que primero, minimicemos nuestro panel aquí. Ahora, usaré una pequeña
X para cerrarlo. Ahora, para hacer esto, lo que haré es, en la nueva línea debajo de la
línea 11, solo usaré el objeto workspace para restablecer sus miembros a una matriz
vacía. De esta manera, no tenemos un administrador antes de intentar agregar un nuevo
miembro al espacio de trabajo. Muy bien, ahora, abriré el terminal nuevamente, y lo
maximizaré, y me dejaré borrar la salida, y luego ejecutaré la aplicación principal
nuevamente. Muy bien. Ahora puede ver que recibimos nuestro mensaje que dice que se
requiere un administrador para agregar miembros a nuestro espacio de trabajo, y luego
también la matriz de miembros del espacio de trabajo está vacía. Y ahora, usaré el
miembro no administrador para crear un nuevo chat y publicar el mensaje en él. Pero
primero, vamos a analizar lo que hacen esos métodos. Así que vamos a cerrar nuestra
terminal de nuevo. Luego regrese a la .php miembro. Luego, primero, veremos el método
de creación de chat. Así que abriré eso. Ahora, create chat acepta el título y luego el
espacio de trabajo al que se debe agregar el chat. En la línea 25, hay otra verificación
para asegurarse de que el miembro que crea el chat realmente pertenece al espacio de
trabajo. Ahora, si lo hacen, creo un nuevo chat en la línea 30, actualizo el título y guardo
el chat en el espacio de trabajo antes de devolverlo. Este método de miembro en la línea
25 también se declara dentro del archivo del espacio de trabajo, por lo que lo veremos
muy rápidamente. Ahora, como puede ver, todo lo que hace es crear una matriz de los
nombres de usuario del miembro del espacio de trabajo, aquí en línea 45. Luego verifica
si el pase y el nombre de usuario del miembro están en esa matriz. En base a eso,
devolverá verdadero o falso. Ahora, para el método de mensaje de publicación a chat,
vayamos aquí, expanda eso. Todo lo que esto hace es aceptar el contenido de la cadena
para el mensaje, y luego el chat en el que debe publicarse. Luego, dentro del método,
creo un nuevo objeto de mensaje, establezco sus propiedades y luego lo guardo en el
chat. Ahora, vamos a crear el chat y publicar en él. Así que volveré a la aplicación.php.
Ahora, antes de hacer nada, eliminemos esta línea 12, donde restablecemos los
miembros del espacio de trabajo. De esa manera no obtenemos ningún error cuando
hacemos este nuevo cambio. Así que simplemente borraré eso por completo. Muy bien.
Luego, debajo de donde imprimimos la información para el espacio de trabajo, voy a crear
un nuevo chat usando nuestro no administrador. Llamaremos a crear chat, y luego llamaré
al chat general. Y luego queremos pasar en el espacio de trabajo de la línea 11. A
continuación, usaré ese mismo miembro para publicar un mensaje. Entonces creo que
solo tendré el mensaje que diga, hola. Luego, el segundo argumento que paso es el chat
de la línea 17. Ahora, para verificar que esto funciona, imprimiré los mensajes de chat y
haré una ejecución final de este archivo de aplicación. Así que usemos nuestro ayudante
de nuevo. Llamaremos a los mensajes del chat. Muy bien, así que déjame abrir el terminal
de nuevo. Vaya a ver, haga clic en terminal. Luego borraré esto y volveré a ejecutar el
archivo. Perfecto. Ahora puede ver en la parte inferior de nuestra salida, tenemos ese
nuevo mensaje que nuestro miembro acme acaba de publicar. Hagamos otra
comprobación para asegurarnos de que la aplicación fallará correctamente si un miembro
crea un chat para un espacio de trabajo del que no forma parte. Así que primero, déjame
borrar la terminal, y luego haré clic en la X aquí para cerrarla. Ahora, debajo de donde
estamos creando los mensajes de chat, crearé un nuevo miembro. Simplemente lo
llamaré member2, y debajo de donde creé, voy a establecer su nombre de usuario.
Permítanme desplazarme un poco hacia arriba aquí. Ahora, debajo de donde creé ese
miembro, los usaré para crear un nuevo chat. Llamémoslo aleatorio, y pasaré en el mismo
espacio de trabajo que se hizo en la línea 11. Ahora todo lo que tenemos que hacer en
este punto es ejecutar el archivo de la aplicación nuevamente. Así que iré a ver, haré clic
en terminal y luego ejecutaré el archivo de la aplicación. Muy bien, ahora puedes ver que
dice, el miembro debe pertenecer a acme.flack.app para crear un chat. Eso es
exactamente lo que esperaba ver. Ahora, no era parte de los requisitos originales, pero
también podría llevar esto un paso más allá para garantizar que los miembros que no son
miembros del espacio de trabajo no puedan publicar un mensaje en uno de sus chats.
Para ello, debe realizar un seguimiento del área de trabajo a través del objeto de chat y, a
continuación, actualizar el mensaje de publicación al método de chat para realizar la
comprobación. A continuación, veremos cómo usar constructores para refinar la forma en
que se crea un objeto.

2.4. Usando constructores

Es posible que esté familiarizado con el conjunto especial de funciones proporcionadas


por PHP que llamamos Métodos mágicos. Cuando se agregan a una clase, se invocan
automáticamente cuando se realiza una acción concreta en un objeto. Aquí nos vamos a
centrar en el Método Mágico _construct. Este método en particular nos permite declarar
un constructor para una clase que se ejecutará cada vez que se cree un nuevo objeto.
Podemos usar esto para hacer que el proceso de inicialización de nuestros objetos sea
mucho más fácil. En este ejemplo se tiene una clase person que no tiene un constructor.
Entonces, para inicializar el nombre y la edad del objeto de persona, establecemos
manualmente el valor de cada propiedad una por una después de que ya esté creada. Si
agregamos un método constructor a la clase, podemos pasar el valor de nuestra
propiedad objects durante la instanciación e inicializarlos dentro del método constructor al
mismo tiempo. Este constructor en particular esperará que el valor del nombre y la edad
se pase cada vez que se cree una nueva persona. Si quisiéramos hacer que uno de los
argumentos fuera opcional, todo lo que tenemos que hacer es asignarle un valor
predeterminado. Entonces, en este caso, cada persona que creemos tendrá una edad
predeterminada de 18 años a menos que pasemos un número diferente. Muchas veces el
constructor solo se usa para asignar argumentos a la propiedad de objeto
correspondiente, lo que puede llevar a mucha redundancia en nuestro código. Para evitar
esto, podemos usar la taquigrafía de promoción constructiva. La promoción constructiva
es un nuevo concepto introducido en la versión ocho de PHP. Implica mover nuestras
declaraciones de propiedad de la definición de clase a la firma constructiva como
argumentos. Al agregar este acceso más hueso a los argumentos, PHP los interpretará
como una propiedad de instancia y automáticamente su signo su valor a lo que pasamos.
Sólo debe utilizar esta abreviatura para promover las propiedades necesarias para crear
el objeto. Cuando no se requiere una propiedad para la inicialización, simplemente puede
dejar la declaración de propiedad en la propia clase. Cuando se utiliza la promoción
constructiva, todavía es posible pasar argumentos regulares al constructor excluyendo el
modificador de acceso. Usemos lo que acabamos de aprender aquí para mejorar nuestro
código existente.

2.5. Pruébelo: creación de objetos refinados

Usando lo que acaba de aprender sobre los constructores de clases, actualice el código
existente para inicializar los datos de cada objeto durante la inicialización. Piense en
formas de utilizar el método constructor para realizar cualquier acción que deba ocurrir
automáticamente cuando se crea un objeto. Por ejemplo, el constructor se puede utilizar
para establecer la dirección URL de un objeto de área de trabajo o para establecer la
fecha de un mensaje después de su publicación. Después de realizar estos cambios, dale
otra ejecución al archivo principal de la aplicación para asegurarte de que el programa
sigue funcionando.

2.6. Compruébalo: creación de objetos refinados

Aquí hay una solución para usar constructores para refinar la forma en que creamos
objetos. Ahora, para crear un miembro, la única propiedad que se requiere es el nombre
de usuario. Así que copiaré lo que tengo en la línea ocho y lo promoveré del constructor
en la línea 12. Ahora, con eso en su lugar, puedo deshacerme de la declaración en la
línea ocho. A continuación, en la clase de espacio de trabajo, sabemos por desafíos
anteriores, para crear un espacio de trabajo necesita un subdominio y un administrador.
Ninguna de esas propiedades existe en la clase workspace en este momento, así que
solo las promoveré como nuevas propiedades del constructor. Entonces, en la línea 12,
comenzaré aceptando ese subdominio, luego debajo de eso, aceptaré el Miembro y le
daré una variable de administración. Ahora, también voy a usar el constructor para seguir
adelante y establecer el administrador de url para nosotros en el momento en que se crea
el objeto. Así que dentro del constructor en la línea 16, llamaré a esto, setUrl y le pasaré
ese subdominio. Luego, debajo de eso, llamaré a esto setAdmin y le pasaré el objeto
admin. A continuación en la clase de chat, solo promocionaré el título aquí. Entonces
puedo eliminar la línea cinco. Y por último, en la clase message, solo requerimos que el
contenido y el autor creen un mensaje, así que promoveré las líneas cinco y seis del
constructor y luego puedo eliminarlas para deshacerme del error. Ahora, al igual que
hicimos con la clase de espacio de trabajo, voy a usar el constructor aquí para establecer
la fecha de nuestro mensaje en el momento en que se crea. Así que en la línea 12,
llamaré a esta fecha. Luego use la función de fecha PHP y pásela una cadena de formato.
Ahora que los constructores están establecidos, tendré que actualizar los lugares en el
código donde creé objetos y establecer manualmente sus propiedades. Así que
comenzaré en el archivo principal de la aplicación donde creé los miembros. Ahora, si
paso el cursor sobre esto, podemos ver que estoy requiriendo ese nombre de usuario de
cadena. Así que seguiré adelante y pasaré eso y luego podré eliminar la línea seis. Ahora
haré lo mismo para el otro miembro, pasándole esa cadena para el nombre de usuario y
luego eliminaré la línea ocho. Ahora, en el archivo de clase de miembro, me desplazaré
un poco hacia abajo para crear el chat y podemos ver que esta instancia en la línea 36
espera que se pase ese título. Así que seguiré adelante y lo pasaré, el título. Con eso en
su lugar, puedo deshacerme de la línea 37. Para crear Workspace, tendré que pasar el
subdominio, así como el objeto miembro actual para el administrador y luego puedo
eliminar las líneas 45 y 46. Por último, en el método PostMessageToChat, esto es esperar
el contenido en el nombre de usuario del objeto miembro actual para el autor. Ahora
puedo eliminar 52 a 54 ya que nuestro constructor de mensajes establecerá la fecha para
nosotros. Ahora, solo para asegurarme de que no he olvidado nada, ejecutaré la
aplicación para asegurarme de que no produzca ningún error. Así que desde el menú de
hamburguesas, abramos el terminal y ejecutaré el archivo principal de la aplicación.
Ampliaré esto solo para asegurarme de que no tengamos ningún error y parece que no lo
tenemos. Así que eso completará este desafío. Nos vemos en la próxima.

3. Ampliación de la funcionalidad mediante composición y herencia


3.1. Herencia

La herencia es un principio de programación orientada a objetos que nos permite reutilizar


código compartiendo estado y comportamiento entre una jerarquía de clases. Este patrón
de reutilización de código implica crear una nueva clase secundaria derivada de otra
clase, a la que nos referimos como padre. Hay tres tipos de herencia que encontrará en el
código que implementa este patrón de diseño. En primer lugar, la herencia única describe
una clase secundaria que hereda propiedades y métodos de una sola clase principal. En
PHP, una clase secundaria no puede heredar datos para más de una clase a la vez. En la
herencia de varios niveles, una clase secundaria existente servirá como clase principal
para otra, creando una relación escalonada entre tres o más clases. Por último, la
herencia jerárquica describe una clase padre con dos o más hijos que heredan sus
propiedades y métodos. La herencia suele ser útil para implementar cuando observa que
dos o más clases en su programa están definiendo los mismos comportamientos.
Digamos que hemos escrito un programa que incluye dos clases, manzana y plátano.
Ambos objetos son frutas con una cubierta exterior que podemos pelar. En lugar de
declarar un método para este comportamiento en cada clase, podemos abstraer esta
funcionalidad en una clase padre llamada fruit, creando una relación entre la clase padre y
sus hijos. En PHP, para formar esta relación entre dos clases, usamos la palabra clave
extends seguida del nombre de la clase padre que el hijo debe extender. La clase
secundaria heredará las propiedades y métodos de su clase principal con el modificador
de acceso público o protegido. Cuando sea necesario, una clase secundaria puede
reemplazar la funcionalidad original de un método que hereda volviendo a declarar el
método en su definición. Para llamar a un método heredado dentro de una clase
secundaria, usamos la misma pseudovariable, tal como lo haríamos para un método
declarado directamente en la clase. Para evitar que una clase se extienda, puede
prefijarla con la palabra clave final. Lo mismo se aplica a la prevención de que una
propiedad o método sea heredado por una clase secundaria. Hay algunas otras cosas a
tener en cuenta que ayudan a garantizar que un programa implemente la herencia
correctamente. Lo primero que debemos considerar es cómo anular correctamente el
método constructor de un padre en una clase secundaria. Al igual que todos los demás
métodos visibles, una clase secundaria heredará implícitamente el método constructor
declarado en su clase padre. Esto incluye cualquier acción que tenga lugar para inicializar
un objeto durante la creación de instancias. Sin embargo, cuando una clase secundaria
declara el método constructor propio, se pierde la funcionalidad heredada. Para evitarlo,
debe llamar explícitamente al constructor primario desde la clase secundaria utilizando la
palabra clave padre seguida del operador de resolución de ámbito. Lo siguiente a
considerar es cuando una clase secundaria hereda un método en el que la clase padre se
refiere a sí misma utilizando la palabra clave self. Tome esta implementación de la clase
fruit, por ejemplo, el método de cáscara ahora es estático e incluye el valor de una nueva
propiedad de nombre estático en el mensaje que devuelve. En la clase secundaria,
volvemos a declarar la propiedad name para reemplazar su valor. Cuando el método
removeCore de la clase secundaria invoca el método de cáscara heredado, es posible
que espere que el mensaje de la cáscara lea que se está pelando la manzana. Pero en
cambio, imprimirá la fruta que se está pelando. Esto sucede porque la palabra clave self
se resuelve automáticamente en la clase a la que pertenece el método de cáscara, que es
fruta. Podemos solucionar esto usando el enlace estático en tiempo de ejecución para
hacer referencia a la clase desde la que llamamos al método en tiempo de ejecución.
Para implementar el enlace estático en tiempo de ejecución, reemplazamos la palabra
clave self en la clase padre con la palabra clave estática. Finalmente, siempre debemos
considerar si la herencia es la mejor solución para ayudarnos a lograr una reutilización
óptima del código al compartir el comportamiento. El uso excesivo de la herencia puede
llevar rápidamente a tener clases estrechamente acopladas, lo que hace que cualquier
actualización de su código en el futuro sea más difícil de realizar. Volviendo a nuestro
diagrama original, ¿qué pasaría si quisiéramos agregar una tercera clase infantil llamada
fresa? La capacidad de pelar esta fruta ya no es relevante. En esta situación, debemos
considerar un co-diseño que utiliza la composición en lugar de la herencia. Aprenderemos
formas de implementar esto en el siguiente video.

3.2. Pruébelo: cree una clase secundaria

Es hora de otro ejercicio de prueba. En este ejercicio, implementará el patrón de diseño


de herencia agregando dos nuevas clases, Channel y DirectMessage. Cada una de estas
clases proporcionará una instancia específica de los tipos de chats que tendrá nuestra
aplicación de mensajería. La publicación de mensajes en un mensaje directo debe
limitarse a los miembros del chat. Lo mismo debería aplicarse a la lectura de los mensajes
del chat. El título de un mensaje directo debe ser una lista separada por comas de los
nombres de usuario de los miembros. Es posible que sea necesaria una actualización del
modificador de acceso actual en la propiedad messages dentro de la clase principal.
Después de realizar estos cambios, cree un nuevo objeto Channel y DirectMessage y
publique algunos mensajes. Verifique que el valor de los mensajes para cada chat es lo
que espera ver en función de que el miembro los recupere.

3.3. Compruébelo: cree una clase secundaria

En este video, te mostraré cómo uso la clase de chat como padre para crear un canal en
la clase secundaria de mensaje directo. También revisaremos los cambios que realicé
para crear, recibir mensajes y publicar en estos nuevos chats. Así que primero quiero
revisar cómo se ven los archivos de clase para el canal en el mensaje directo. Así que los
abriré. Muy bien. La clase de canal es muy básica. No tiene ningún requisito especial
fuera de lo requerido por la clase de chat principal. Todo lo que tenemos aquí es este
único método Get Messages y explicaré por qué lo tiene más adelante. Los mensajes
directos, por otro lado, son más un chat privado entre los miembros invitados. Así que
declaré un constructor para esta clase que promueve la propiedad de un miembro
requerido en la línea ocho. Y luego, dentro del método, uso la matriz de objetos miembro
para crear una nueva matriz con solo sus nombres de usuario. Y en la línea 12 uso los
nombres de usuario para crear el título del chat. Ahora, dado que esta es una clase
secundaria en la que estamos, debemos recordar llamar manualmente al constructor de la
clase padre si tiene uno. Así que eso es lo que estoy haciendo aquí en la línea 14. Y
luego le paso un título. El primer requisito de este desafío implica crear una nueva
instancia de objeto de cada una de estas clases. Entonces, primero, si miramos la
aplicación.php la línea 15 muestra un ejemplo de cómo se crearon previamente los chats.
Invocaría el método create chat en el objeto miembro creando el chat y pasando los
detalles necesarios para hacerlo. Ahora bien, esto sigue siendo lo mismo, pero desde
entonces he dividido esta funcionalidad en dos métodos separados en la clase miembro
para cada tipo de chat. Así que permítanme pasar a la clase de miembros. Me desplazaré
un poco hacia abajo aquí. Ahora, podría haber mantenido el mismo método Crear chat y
simplemente aceptar un parámetro que especificara el tipo de chat que quería crear, pero
prefiero tener un método diferente para cada tipo de chat para poder mantener esa lógica
separada. Y cuando realmente creo estos chats, tengo un método para llamar que es un
poco más expresivo que simplemente crear Chat. Ahora crear canal es exactamente el
mismo que Crear chat. Acabo de cambiar el método en los nombres de las variables.
Crear mensaje directo es lo mismo, pero también cambio ese parámetro de título por el
parámetro de un miembro. Y luego en línea 49, lo hice para que este método actualice la
matriz de ese miembro para incluir automáticamente al miembro que crea el mensaje
directo en caso de que aún no esté incluido. Ahora, en realidad voy a usar estos métodos
para crear un nuevo objeto de cada una de estas clases. Entonces, en el archivo principal
de la aplicación, voy a usar el objeto admin para crear un canal y luego pensaré que usaré
el miembro A para crear un mensaje directo. Así que crearé mi variable de canal y luego
usaré el administrador para llamar a Crear canal. Ahora solo le daré un título y le pasaré
nuestro espacio de trabajo de la línea 10. Luego, debajo de eso, crearé un mensaje
directo. Y luego, para la matriz de miembros, simplemente pasaré el miembro B y luego,
por supuesto, el espacio de trabajo. Muy bien. Ahora, para imprimirlos, usaré nuestro
ayudante. Y luego este ayudante también tiene un segundo parámetro que puede pasar
para especificar si desea embellecer el contenido. Voy a configurar eso en True para que
nuestra salida sea un poco más limpia y fácil de entender una vez que la veamos en el
terminal. Muy bien, y haré esto de nuevo para nuestro mensaje directo. Y entre los dos,
en realidad voy a imprimir una línea en blanco para que la salida sea más fácil de leer.
Ahora a abrir el terminal para que podamos ejecutar nuestro archivo. Ampliaré esto. Muy
bien. Ahora, si me desplazo hacia arriba, puedes ver que tenemos nuestro objeto channel.
Tiene esa propiedad de mensajes heredada de la clase de chat y el título. Y luego el
mensaje directo también tiene esa propiedad de mensajes heredados, el título que
creamos a partir de los nombres de usuario de los miembros y luego nuestras dos
propiedades con respecto a nuestros miembros. Ahora el siguiente requisito es publicar
un mensaje. Y para hacer eso, necesitaba poner un control para la clase de mensaje
directo específicamente que los miembros del seguro pueden publicar en el chat. Así que
déjame seguir adelante y aclarar esto y cerraré la terminal. Y abramos miembro.php.
Ahora, desplácese un poco hacia abajo. Ahora, para este paso, lo primero que hice fue
actualizar el método de mensaje de publicación a chat para llamar a un método de
mensaje de anuncio en la clase de chat. Este método acepta la publicación del miembro
actual en el chat y el contenido del mensaje. Entonces, si miramos esto en la clase de
chat, podemos ver que después de que se aceptan esos argumentos, simplemente crea
un nuevo objeto de mensaje y luego guarda ese mensaje en el chat. Ahora en la clase de
mensaje directo, anulo el método del mensaje del anuncio para incluir la condición
necesaria para verificar el miembro del chat antes de que se publique el mensaje. Así que
eso es lo que está sucediendo aquí en línea 19 y esto tiene la verificación de miembros en
el objeto de chat es muy similar a lo que vimos con la clase de espacio de trabajo. Realiza
la comprobación del miembro dentro de la matriz de un miembro por nombre de usuario.
Así que ahora vamos a publicar los mensajes. Volveré al archivo principal de la aplicación
y para publicar en el canal, usaré el miembro administrador. También usaré el
administrador para publicar en el mensaje directo solo para verificar que la verificación
funcione. Debajo de donde declaré el canal, usaré el administrador para llamar al mensaje
de publicación para chatear. Solo saludaré y le daré nuestro canal. Luego, debajo de la
declaración de mensaje directo, haré la misma llamada, pasaré algo de contenido solo
diciendo hola y el chat de mensaje directo. Voy a abrir nuestra terminal aquí y voy a
expandir eso y ejecutar el archivo. Muy bien. Ahora, si me desplazo hacia arriba, puede
ver que el objeto channel tiene el mensaje que fue publicado por el administrador antes
del mensaje directo. El mensaje es propiedad todavía está vacío. Entonces, aquí, en la
parte superior de la salida, puede ver que dice que Acme Admin no tiene acceso a este
chat. Así que está funcionando de la manera que esperamos. Si actualizo la línea 21 para
usar realmente un miembro que forma parte del chat, solo usaré el miembro B. Luego
expandiré esto y lo ejecutaré nuevamente y me desplazaré hacia arriba. Puede ver que
ese mensaje se ha agregado a nuestro objeto de mensaje directo. Ahora para limpiar el
terminal minimizaré esto y lo cerraré. Y para el último requisito teníamos que cambiar la
forma en que se accedía a los mensajes de un chat. Así que voy a ir a charlar.php y me
desplazaré hacia arriba aquí. Aquí puede ver en línea cinco la propiedad de mensajes se
actualizó para tener un modificador de acceso protegido para que las clases secundarias
aún tengan acceso, pero para el resto de la aplicación, son privadas. Luego, tanto en la
clase de canal como en la de mensaje directo, creo este método Get Messages. Desde la
clase channel, solo devolverá esos mensajes sin restricciones. Pero luego, en los
mensajes directos, tengo una verificación similar a lo que vimos dentro del mensaje
publicitario. Eso verificará si hay ese miembro dentro del chat antes de que se devuelvan
los mensajes. Ahora, si se pregunta por qué no agregué el método get messages a la
clase de chat y lo anulé de la manera en que lo hago con add message, para anular un
método padre, la firma del método debe ser la misma. Entonces, en el caso de un chat
normal o un canal, en este caso no hay necesidad de este acceso por propiedad. Un
mensaje directo utiliza aquí la línea 30. Hacerlo de esta manera también hace que sea
necesario pasar un miembro a este método, mientras que si lo hice al revés, tengo que
hacer que este parámetro sea opcional. Ahora, para ver cómo funciona esto en acción,
imprimiré el valor de get message para cada objeto de chat. Así que vuelve a la
aplicación.php, luego eliminaré esta salida anterior ya que ya no la necesitamos. Y luego
usaré nuestro objeto channel y llamaré a recibir mensajes. Ahora, haré lo mismo para el
objeto de mensaje directo, pero esta vez tendré que pasar el miembro que está intentando
acceder a los mensajes. Así que usaré el miembro B en este caso. Luego podemos
ejecutar el archivo en el terminal. Ampliaré esto. Muy bien. Ahora puedes ver que
tenemos los mensajes impresos en cada chat. El primero aquí es para la clase de canal y
puede ver que ese mensaje es del administrador del acné. Y luego el segundo es del
mensaje directo y es del Miembro B del acné. Ahora, solo para asegurarme de que esa
verificación nuevamente funcione de la manera en que espero actualizar la línea 24 para
pasar el administrador para asegurarme de que el administrador no pueda acceder a
estos mensajes. Así que vamos a expandir esto de nuevo y ejecutar el archivo. Ahora
puede ver que recibimos el mensaje de que el administrador de Acme no tiene acceso a
este chat. Así que eso lo hará para este. En el desafío final, haremos algunas
actualizaciones para mejorar aún más la composición de nuestro código.

3.4. Compartir reglas y comportamientos

En el video anterior, vimos cómo extender la funcionalidad a una de nuestras clases a


través de la herencia. Si bien la herencia ayuda a reutilizar fácilmente el código, a veces
una clase puede necesitar más control sobre cómo implementa la herencia codificada, lo
que crea la necesidad de una opción más extensible. Afortunadamente, hay tres opciones
entre las que podemos elegir para ayudar a lograr esto. Comenzaremos mirando las
clases abstractas. Una clase abstracta es lo mismo que una clase normal, excepto que no
podemos usarla para crear nuevos objetos. En cambio, el propósito de una clase
abstracta es definir un conjunto de propiedades y métodos requeridos que una clase
secundaria debe implementar sin describir cómo hacerlo. Podemos usar el ejemplo de
clase del video anterior para demostrar esto. Por supuesto, ya hemos establecido que
estas dos clases son un tipo de fruta que se puede pelar, pero creo que podemos estar de
acuerdo en que la forma en que pelamos una manzana es muy diferente de cómo
pelaríamos un plátano. Entonces, para dar a las clases de niños más flexibilidad sobre
cómo implementan el método de peeling, podemos actualizar el método para que sea
abstracto, lo que nos permite eliminar su implementación. Dado que la clase de fruta
ahora tiene un método abstracto en su definición, también debe declararse como
abstracta. Con esta actualización de la clase principal, ambas clases secundarias ahora
pueden definir implementaciones independientes del método compartido sin tener que
reemplazar el comportamiento original. Veamos cómo se compara esto con el uso de una
interfaz. Una interfaz es un contrato que especifica qué métodos debe tener una clase sin
proporcionar la implementación del método. Esto es similar a lo que acabamos de ver con
las clases abstractas, excepto que dos clases que implementan la misma interfaz no
tienen que pertenecer a la misma jerarquía de clases. En este ejemplo, nuestra fruta de la
clase principal sigue siendo abstracta, pero hemos introducido una nueva clase
secundaria. Aunque el método de peeling de los padres no se aplica a esta nueva clase,
todavía se requiere proporcionar una implementación; Las interfaces nos permiten tomar
una ruta diferente. Al mover el método peel a una interfaz, podemos actualizar nuestro
código para que se implemente solo en las clases donde se aplica. Usamos la palabra
clave interface seguida de su nombre para definir una nueva interfaz. Para implementar la
interfaz en una clase, utilice la palabra clave implements después del nombre de la clase.
La última opción para revisar es un rasgo. Usamos un rasgo para agrupar métodos de
comportamiento relacionado de una manera consistente que cualquier clase puede usar.
Tome nuestra clase de manzana existente en esta nueva clase de zanahoria como
ejemplo. A pesar de que estas dos clases son de diferentes tipos, ambos son alimentos
que proporcionan una fuente de valor nutricional. Así que digamos que queríamos obtener
el total de carbohidratos y calorías de una manzana y una zanahoria. Suponiendo que
estos valores se calculan de la misma manera para ambos, podemos definirlos como
métodos una vez dentro de un rasgo y luego usarlos en ambas clases. - Para definir un
rasgo, use la palabra clave rasgo seguida de un nombre. A continuación, para usar el
rasgo dentro de una clase, declare una instrucción use al principio de la definición de
clase. Una clase puede usar varios rasgos actualizando la instrucción use con la lista
separada por comas del nombre de cada rasgo. Llamar a un método heredado de un
rasgo es lo mismo que llamar a un método de instancia. Los métodos de un rasgo
también tendrán prioridad sobre cualquier método heredado de una clase padre que
comparta la misma firma. Antes de pasar al siguiente ejercicio, hagamos un resumen
rápido. Las clases abstractas proporcionan más flexibilidad sobre cómo una clase
secundaria implementará los métodos que hereda de un padre. Una interfaz también
puede dar esta flexibilidad, pero no requiere que las clases estén en la misma jerarquía.
Finalmente, un rasgo puede agrupar métodos de funcionalidad común para su uso en
cualquier clase donde se aplique el comportamiento de los métodos.

3.5. Pruébalo: elige tu propia aventura

¡Lo lograste! Has llegado al ejercicio final de este curso. Para este ejercicio, tendrás la
oportunidad de elegir tu propia aventura.

Su desafío es usar lo que acaba de aprender para actualizar su código, de modo que use
una clase abstracta, una interfaz o un rasgo.

Aquí hay un resumen rápido de cada uno. Hacer que una clase sea abstracta significa
que ya no se puede crear una instancia, pero aún proporciona una forma de definir una
interfaz para que otras clases la extiendan.

Las interfaces son similares, excepto que no es necesario que las clases que las
implementan estén en la misma jerarquía de clases. Finalmente, los rasgos le permitirán
definir un conjunto de propiedades y métodos que se pueden compartir entre varias
clases.

A diferencia de las clases e interfaces abstractas, un rasgo incluirá la implementación de


cualquier método que defina.

Si no está seguro de cómo implementar cualquiera de estos en su código, tómese unos


minutos para revisar los ejemplos concretos proporcionados en el video anterior.

3.6. Compruébalo: elige tu propia aventura

Bienvenido al video de la solución final. Para este desafío, solo es necesario implementar
un ejemplo de composición en el código mediante una clase abstracta, una interfaz o un
rasgo.

Aquí te mostraré un ejemplo de cada uno. Por lo tanto, actualmente es posible crear un
chat usando la clase de chat y puedo demostrarlo creando un nuevo objeto de chat. Y
luego lo que haré es imprimirlo en el terminal para que podamos verificar que el chat fue
creado.
Así que abra el terminal y ejecute el archivo, y puede ver que tenemos nuestro objeto de
chat. Ahora que tenemos el mensaje directo y las clases de canal, tiene más sentido para
mí tener siempre un chat de uno de esos tipos.

Entonces, para asegurarme de que eso suceda, puedo actualizar la clase de chat para
que sea abstracta. De esa manera, solo sirve como modelo para sus clases infantiles. Así
que iré al chat punto PHP y aquí en la línea tres agregaré la palabra clave abstracta y
luego ejecutaré la aplicación nuevamente.

Y ahora puedes ver que obtenemos un error fatal que indica que no podemos instanciar
una clase abstracta. Así que eso es exactamente lo que necesitamos.

Ahora borraré esto, cerraré la terminal y luego haré esquemas comunes de ocho a nueve
para evitar errores cuando volvamos a ejecutar la aplicación.

A continuación, si miramos el espacio de trabajo y la clase de mensaje directo, puede ver


que ambos tienen este método hasMember. Me desplazaré hacia abajo aquí.

Ahora, el contenido que está dentro de cada uno de estos métodos es diferente, pero si
miras la línea 50 aquí y luego en el mensaje directo, la línea 41, las firmas para ambos
métodos son las mismas.

Este es un gran ejemplo de dos clases y dos jerarquías diferentes que comparten la
misma funcionalidad. Entonces, digamos que quería exigir que estas clases no solo
implementaran este método, sino algunas otras que son específicas de las clases que
tienen miembros que pueden unirse.

Podría usar una interfaz para esto. Así que he creado una interfaz que se puede unir y la
interfaz que se puede unir solo incluye la firma para ese método hasMember. Entonces,
para implementar esto en nuestras clases, puedo usar la palabra clave implements,
seguida de ese nombre de interfaz, y haré lo mismo para el espacio de trabajo.

Y ahora ambas clases son técnicamente necesarias para tener ese método hasMember.
Ahora, para demostrar esto, continuaré y comentaré el método hasMember dentro de la
clase workspace. Y si me desplazo hacia arriba puedes ver ahora que tenemos un error y
pasando el cursor sobre él dice, Workspace no implementa el método hasMember.

Por lo tanto, las interfaces son realmente una excelente manera de asegurarse de que
sus clases agreguen el comportamiento de sus objetos que espera que tengan. Así que
vamos a descomentar esto para que nuestra clase funcione de nuevo. Ahora, para el
último ejemplo, creé este rasgo HasUniqueId que me permitiría agregar una propiedad ID
a cualquier clase que elija.

Esta es una excelente manera de tener un medio único para identificar diferentes objetos.
Por lo tanto, el rasgo tiene esta propiedad de identificador privado en la línea cinco y dos
métodos para recuperar y establecer el valor de la propiedad de identificación. Cuando
establezco el ID en la línea nueve, uso el método get class para agregar el nombre de la
clase al comienzo de la secuencia.

De esta manera, es más fácil identificar el objeto al que pertenece el ID. Entonces, para
usar esto, actualizaré la clase miembro como ejemplo. Así que abramos el punto miembro
PHP, y para usar el rasgo usamos la palabra clave used seguida del nombre de los
rasgos y luego dentro del constructor para esta clase llamaré al método para establecer el
ID.

Ahora, para ver este ID en el objeto en el archivo principal de la aplicación, imprimiré


nuestro objeto miembro que tenemos en la línea cinco. Ahora para abrir el terminal y
ejecutar el archivo. Puede ver que el objeto miembro tiene efectivamente la nueva
propiedad ID con el nombre de la clase anexado a la secuencia de ID aleatorio. Eso es
todo por este.

Espero que trabajar a través de este escenario de aplicación de mensajería haya sido útil
para comprender los patrones de diseño orientados a objetos en PHP. Te animo a
practicar los conceptos cubiertos en este curso al continuar agregando a lo que hemos
hecho hasta ahora en la aplicación. También puede usar el cuestionario posterior a la
evaluación para probar qué tan bien ha comprendido los temas que hemos cubierto.

Conclusión
Aprendiendo más sobre PHP

Felicidades, has dominado los conceptos básicos de la programación orientada a objetos


en PHP. Si desea ver más de lo que PHP tiene para ofrecer, puede consultar el vasto
catálogo de cursos introductorios y avanzados de PHP aquí en LinkedIn Learning.

También hay una ruta de aprendizaje completa orientada a ayudarlo a convertirse en un


desarrollador de PHP. Desde una búsqueda rápida en la web, también puede encontrar
plataformas gratuitas de código abierto como On-ramp.

La rampa de acceso proporciona una guía a su propio ritmo para aumentar sus
habilidades en uno de los marcos más populares de PHP. Como siempre, siéntase libre
de conectarse conmigo aquí en LinkedIn. Gracias por verte y espero verte en mi próximo
curso.

También podría gustarte