6. ¿Qué es la programación orientada a objetos?
La programación orientada a objetos (POO) es un paradigma de la programación en el que se crean objetos para la manipulación de datos y donde, por lo general, cada objeto ofrece una funcionalidad especial.
- La idea básica de la POO es el uso de objetos para modelar cosas del mundo real.
- POO nos ayuda a la reutilización del código.
Imagina que tienes un colegio o escuela con 1000 estudiantes y 100 profesores, sería ilógico estar construyendo objetos para cada uno de ellos. Las clases son, como una especie de máquina constructora de objetos al momento segun demanda.
Hay de varios tipos:
- Función constructora (antiguo)
- Clase (actual)
6.1. Funciones constructoras:
- Un nombre de función constructora generalmente comienza con una letra mayúscula. Esta convención se utiliza para hacer que la función constructora sean más fácil de reconocer en el código.
- La palabra clave new se usa para crear una nueva instancia del objeto (crear un nuevo objeto)
Declaración de función + 1 atributo + instancia:
El constructor Object():
6.2. Clases:
Con la llegada de ES6 (ECMAScript 2015), se introducen las clases en JavaScript que proveen una sintaxis mucho más clara y simple para crear objetos y lidiar con la herencia. Es una mejora sintáctica de las funciones constructoras que se basaban en prototipos, ésto no cambió ni agregó funcionalidad, pero trajo una mejor organización del código.
Existen 2 formas para definir una clase y 2 tipos de expresión de clase:
- Declaración de clase
- Expresión de clase
- Anónima: No tiene un nombre.
- Nombrada: Tiene un nombre interno que solo es accesible dentro de la clase.
Declaración de clase:
Expresión de clase:
Ambos enfoques crean una clase llamada Persona, pero con las expresiones de clases se tiene más flexibilidad para definirlas de forma dinámica.Expresión de clase:
En el siguiente ejemplo, la clase se define sin un nombre específico (anónima) y se asigna a la constante Persona. A partir de ahí, se puede utilizar de la misma manera que una clase declarada.
Expresión de clase nombrada:
En este ejemplo, la clase PersonaInterna es accesible solo dentro del bloque de la expresión pero no fuera de él. Esta característica permite encapsular el nombre de la clase y evitar conflictos de nombres.
Cuándo usar expresión de clase:
- Clases dinámicas: Cuando necesitas definir clases de forma condicional o dentro de funciones.
- Mantener el código limpio: Usa clases anónimas si no necesitas referenciar el nombre fuera del bloque.
Sintaxis de una clase:
Clase + constructor:
Clase + constructor + 1 método:
Clase con llaves en atributos y argumentos:
Clase sin llaves en atributos y argumentos:
6.2.1. Método de instancia:
Ejemplo 1
En este ejemplo, el uso de llaves en atributos como en argumentos es necesario para poder renombrar el valor predeterminado del atributo tipo si diese el caso.
Clase + constructor + 1 valor de atributo predeterminado:
- Se declara una clase llamado Persona
- Se crea un constructor, se le pasa 1 atributo llamado tipo con valor predeterminado, el resto sin valores
- Se crea un método llamado descripcion
- Se crean 2 objetos llamados persona_1, persona_2 y se le pasan argumentos a cada uno.
Veamos éste otro ejemplo con la misma lógica:
Veamos una clase sin método con la misma lógica. No se recomienda, esto implica tener que construir la respuesta completa en cada llamada a la clase, se recomienda crear un método dentro de la clase y llamarlo.
6.2.2. Método estático:
Con un método estático, no requiere crear un objeto mediante instancia para que funcione.
-
Acceso global: pueden utilizarse en cualquier lugar del código sin necesidad de crear una instancia de la clase. Esto hace que sean accesibles de manera global y fácil de usar.
-
Optimización de recursos: al no requerir la creación de instancias, los métodos estáticos pueden ser más eficientes en términos de recursos.
-
Mantenimiento simplicado: cuando un método no necesita acceder a propiedades de instancia, es recomendable definirlo como estático, lo que simplifica el mantenimiento y reduce la complejidad del código.
Clase + método estático:
Clase + método de instancia + método estático:
Supongamos que estamos construyendo un sistema de gestión de usuarios y necesitamos generar un ID único para cada usuario.
En este caso, el método estático generarID se utiliza para crear ID únicos sin necesidad de crear una instancia de la clase Usuario.
6.2.3. Propiedad estática:
Además de los métodos estáticos, las clases en JavaScript también pueden tener propiedades estáticas, que son variables que pertenecen a la clase en su totalidad y no a las instancias individuales. A partir de ES2022 JavaScript permite definir propiedades estáticas de manera más sencilla dentro de la clase. Esto se hace utilizando la palabra clave static antes de la definición de la propiedad.
Clase + propiedad estática:
En este caso usuariosMax es una propiedad estática que pertenece a la clase Configuracion. Al ser estática, no puede ser accedida a través de métodos de instancias de la clase.
Acceso a propiedades estáticas desde métodos estáticos:
Los métodos estáticos pueden acceder a otras propiedades y métodos estáticos usando this, que en este contexto se refiere a la clase.
Clase + propiedad estática + método estático + alcance:
Veamos un ejemplo donde combinamos métodos y propiedades estáticas para modelar un sistema de configuración.
version y conexionesMaximas son propiedades estáticas de la clase Sistema y el método obtenerInfo() proporciona información relevante sobre el sistema
Buenas prácticas:
- Usa métodos estáticos para lógica no específica de instancias: Ideal para funciones utilitarias, cálculos compartidos o valores constantes.
- Evita abusar de los métodos estáticos: Usa instancias y métodos de instancia cuando necesites trabajar con datos específicos de objetos.
- Organiza las propiedades estáticas: Colócalas al inicio de la clase para mayor claridad.
- Documenta el propósito de los métodos estáticos: Deja claro en los comentarios cuándo y por qué un método debe ser estático.
Conclusión:
Las propiedades y métodos estáticos son herramientas poderosas para agregar funcionalidades compartidas a las clases en JavaScript. Son útiles para crear funciones utilitarias, mantener valores constantes y manejar estados compartidos. Sin embargo, deben usarse con moderación y no como sustituto de la lógica basada en instancias.
6.3. Nombres de propiedad computadas:
Los nombres de propiedad computadas permiten utilizar una expresión dentro de corchetes ([ ]) para definir el nombre de una propiedad. Esto significa que el nombre de la propiedad se calcula en tiempo de ejecución en lugar de ser un valor literal. En el contexto de las clases, estas pueden usarse para definir tanto métodos como propiedades.
Al definir métodos en una clase, los nombres de propiedad son útiles cuando el nombre del método no se conoce hasta tiempo de ejecución.
Ejemplo 1
En este ejemplo, el nombre del método se calcula a partir del valor de la variable metodoDinamico, lo que permite definir métodos de manera más dinámica.
Clase + 1 método con nombre computado:
Los nombres de propiedad computadas son especialmente útiles en los siguientes escenarios:
- Asignación Dinámica de Propiedades o Métodos: Cuando el nombre de una propiedad o método depende de una entrada del usuario o de otra lógica que se ejecuta en tiempo de ejecución.
- Configuración Basada en Datos Externos: Si necesitas definir propiedades basadas en un conjunto de datos dinámico, los nombres de propiedad computados facilitan este proceso.
- Evitar Redundancia en Código Repetitivo: Puedes crear múltiples métodos o propiedades usando un patrón común sin tener que escribir cada uno manualmente.
Ejemplo 2
En este ejemplo, los métodos se definen usando los valores almacenados en el array acciones, lo que evita la repetición de código y facilita la creación de métodos con nombres similares.
clase + métodos con prefijos comunes:
Aunque las propiedad computados son una característica poderosa, hay algunas consideraciones importantes a tener en cuenta:
- Legibilidad del Código: El uso excesivo puede afectar la legibilidad del código. Es importante usarlos cuando realmente agreguen valor.
- Errores de Tipo: Asegúrate de que la expresión utilizada para calcular el nombre de la propiedad sea válida y retorne un string. De lo contrario se lanzará un error.
Conclusión:
Los nombres de propiedad computadas en clases son una característica útil de JavaScript que permite definir métodos y propiedades de forma dinámica. Cuando se usan adecuadamente pueden simplificar la configuración de objetos y clases, evitar redundancias y hacer que el código sea más flexible. Sin embargo, es importante no abusar de esta técnica para mantener la claridad del código.
6.4. Herencia:
La herencia en JavaScript permite que una clase hija adquiera las propiedades y métodos de una clase base, lo cual facilita la creación de jerarquías de clases. La clase hija puede ampliar o modificar la funcionalidad heredada para adaptarla a necesidades específicas.
Sintaxis de la herencia:
Para crear una clase que extienda otra clase, se utiliza la palabra clave extends:
En este ejemplo, la clase Perro extiende la clase Animal, lo que le permite acceder al método hacerSonido() de la clase base.
Beneficios de la Herencia:
- Reutilización del Código: Se evita la duplicación al reutilizar el comportamiento común definido en la clase base.
- Extensión de Funcionalidades: La clase hija puede añadir características o cambiar el comportamiento de los métodos heredados.
- Organización y Mantenimiento: Ayuda a estructurar el código en niveles jerárquicos, haciendo más fácil comprender y mantener la lógica.
Editor de código utilizado: