Unidad1
“Paradigma Orientada a Objetos”
La programación orientada a objetos surgió como una alternativa a estas
características de la programación estructurada. El propósito de su creación fue
también acercar el manejo de las estructuras de un programa al manejo de las
cosas en el mundo real, de ahí el nombre "objeto" como algo genérico, que puede
representar cualquier cosa tangible.
Este nuevo paradigma se basa principalmente en dos conceptos
clave: clases y objetos. Todos los demás conceptos, igualmente importantes, se
basan en estos dos.
➢ ¿Qué son las Clases y los Objetos?
Imagina que recientemente compraste un auto y decidiste modelar ese auto
utilizando programación orientada a objetos. Tu auto tiene las características que
estabas buscando: motor 2.0 híbrido, azul oscuro, cuatro puertas, cambio
automático, etc. También tiene comportamientos que probablemente fueron el
motivo de tu compra, como acelerar, reducir la velocidad, encender los faros, tocar
la bocina y tocar música. Podemos decir que el auto nuevo es un objeto, donde
sus características son sus atributos (datos vinculados al objeto) y sus
comportamientos son acciones o métodos.
Tu auto es un objeto tuyo, pero en la tienda donde lo compraste habían otros
tantos, muy similares, con cuatro ruedas, volante, cambio, espejos retrovisores,
faros, entre otras partes. Ten en cuenta que, aunque tu auto es único (por
ejemplo, tiene un registro único en el Departamento de Tránsito), puede haber
otros con exactamente los mismos atributos, o similares, o incluso totalmente
diferentes, pero que aún se consideran autos. Entonces podemos decir que tu
objeto se puede clasificar (es decir, tu objeto pertenece a una clase) como un
auto, y que tu auto no es más que una instancia de esa clase llamada "auto".
Así, abstrayendo un poco la analogía, una clase es un conjunto de características
y comportamientos que definen el conjunto de objetos pertenecientes a esta clase.
Tenga en cuenta que la clase en sí es un concepto abstracto, como un molde, que
se vuelve concreto y palpable a través de la creación de un objeto. Llamamos a
esta creación de instanciación de clase, como si estuviéramos usando este molde
(clase) para crear un objeto.
Encapsulamiento, herencia y polimorfismo: las principales características de la
POO
Las dos bases de la POO son los conceptos de clase y objeto. De estos conceptos
derivan algunos otros conceptos extremadamente importantes al paradigma, que
no solo lo definen, sino que son las soluciones a algunos problemas de la
programación estructurada. Los conceptos en cuestión son el encapsulamiento,
la herencia, las interfaces y el polimorfismo.
Encapsulamiento:
Aun usando la analogía del auto, sabemos que tiene atributos y métodos, es decir,
características y comportamientos. Los métodos del auto, como acelerar, pueden
usar atributos y otros métodos del auto, como el tanque de gasolina y el
mecanismo de inyección de combustible, respectivamente, ya que acelerar
consume combustible.
Sin embargo, si algunos de estos atributos o métodos son fácilmente visibles y
modificables, como el mecanismo de aceleración del auto, esto puede darle
libertad para realizar cambios, lo que resulta en efectos secundarios imprevisibles.
En esta analogía, una persona puede no estar satisfecha con la aceleración del
auto y cambia la forma en que se produce, creando efectos secundarios que
pueden hacer incluso con que el auto ni ande, por ejemplo.
En este caso, decimos que el método de aceleración de su auto no es visible
desde el exterior del mismo auto. En la POO, un atributo o método que no es
visible desde afuera del mismo objeto se llama "privado"(OCULTO) y cuando está
visible, se llama "público"(VISIBLE).
Pero entonces, ¿cómo sabemos cómo acelera nuestro auto? Es simple: no lo
sabemos. Solo sabemos que para acelerar hay que pisar el acelerador y el objeto
sabe cómo realizar esta acción sin exponer cómo lo hace. Decimos que la
aceleración del auto está encapsulada, porque sabemos lo que hará cuando
ejecutemos este método, pero no sabemos cómo y, de hecho, al programa no le
importa cómo lo hace el objeto, solo que lo haga.
Lo mismo ocurre con los atributos. Por ejemplo: no sabemos cómo el auto sabe
qué velocidad mostrar en el velocímetro o cómo calcula su velocidad, pero no
necesitamos saber cómo se hace eso. Solo necesitamos saber que nos dará la
velocidad adecuada. Se puede leer o cambiar un atributo encapsulado
desde getters(Mostrar) y setters(Definir).
Ese encapsulamiento de atributos y métodos evita la llamada fuga de alcance,
donde un atributo o método es visible para alguien que no debería poder verlo,
como otro objeto o clase. Esto evita confundir el uso de variables globales en el
programa, facilitando identificar en qué estado estará cada variable en cada
momento del programa, ya que la restricción de acceso nos permite identificar
quién puede modificarla.
Herencia
En nuestro ejemplo, acabas de comprar un auto con los atributos que buscabas. A
pesar de ser únicos, hay autos con exactamente los mismos atributos o formas
modificadas. Digamos que compraste el modelo Fit de Honda. Este modelo tiene
otra versión llamada WR-V (o "Honda Fit Cross Style"), que tiene muchos de los
atributos de la versión clásica, pero con algunas diferencias muy grandes para
transitar por caminos de tierra: el motor es híbrido (acepta alcohol y gasolina),
tiene un sistema de suspensión diferente, y supongamos que además tenga un
sistema de tracción diferente (tracción a las cuatro ruedas, por ejemplo). Vemos
entonces que no solo cambian algunos atributos sino también algunos
mecanismos (o métodos, traduciéndose a POO), pero esta versión "cross" sigue
siendo el modelo Honda Fit, es decir, es un tipo del modelo.
Cuando decimos que una clase A es un tipo de clase B, decimos que clase
A hereda las características de la clase B y que la clase B es madre de la clase A,
estableciendo entonces una relación de herencia entre ellas. En el caso del auto,
decimos que un Honda Fit "Cross" es un tipo de Honda Fit, y lo que cambia son
algunos atributos (tapabarros reforzado, altura de la suspensión, etc.), y uno de los
métodos de la clase (acelerar, ya que ahora hay tracción en las cuatro ruedas),
pero todo lo demás sigue igual, y el nuevo modelo recibe los mismos atributos y
métodos que el modelo clásico.
Muchos de los métodos de los autos son comunes en muchos automóviles. Tanto
un auto como una motocicleta son clases cuyos objetos pueden acelerar, frenar,
encender los faros, etc., ya que son comunes a los automóviles. Podemos decir,
entonces, que tanto la clase "auto" como la "motocicleta" son "automóviles".
Cuando dos (o más) clases tienen comportamientos comunes que pueden
separarse en otra clase, decimos que la "clase común" es una interfaz, que
puede ser "heredada" por las otras clases. Tenga en cuenta que colocamos la
interfaz como una "clase común", que puede ser "heredada" (con comillas),
porque una interfaz no es exactamente una clase, sino un conjunto de métodos
que todas las clases que heredan de ella deben tener (implementar) - por lo tanto,
una interfaz no es "heredada" por una clase, sino implementada. En el mundo del
desarrollo de software, decimos que una interfaz es un "contrato": una clase que
implementa una interfaz debe proporcionar una implementación para todos los
métodos que define la interfaz y, a cambio, la clase de implementación puede
decir que es del tipo de interfaz. En nuestro ejemplo, "auto" y "motocicleta" son
clases que implementan los métodos de la interfaz "automóvil", por lo que
podemos decir que cualquier objeto de estas dos primeras clases, como una
Honda Fit o una motocicleta Yamaha, son automóviles.
Un pequeño detalle: una interfaz no puede ser heredada por una clase, sino
implementada. Sin embargo, una interfaz puede heredar de otra interfaz,
creando una jerarquía de interfaces. Usando un ejemplo completo con autos,
decimos que la clase "Honda Fit Cross" hereda de la clase "Honda Fit", que a su
vez hereda de la clase "Auto". La clase "Auto" implementa la interfaz "Automóvil"
que, a su vez, puede heredar (por ejemplo) una interfaz llamada
"MedioDeTransporte", ya que tanto un "automóvil" como un "carro" son medios de
transporte, aunque un carro no sea un automóvil.
Cuál es la diferencia entre una clase y un objeto?
En la Programación Orientada a Objetos, tanto las clases como los objetos son
elementos fundamentales. Sin embargo, existen diferencias significativas entre
ellos.
Una clase es una plantilla o modelo que define las características y
comportamientos de un objeto. Es como un plano o molde que describe cómo
debe ser creado un objeto. En una clase se definen los atributos (propiedades) y
los métodos (acciones) que tendrá el objeto.
Por otro lado, un objeto es una instancia de una clase. Es decir, es una
representación concreta de la clase, que posee sus atributos y puede ejecutar sus
métodos. Los objetos son creados a partir de una clase y pueden tener valores
diferentes en sus atributos.
La diferencia clave entre una clase y un objeto es que la clase es la definición
abstracta de un concepto o entidad, mientras que el objeto es una instancia
concreta de esa clase.
Para comprender mejor la diferencia, veamos un ejemplo:
• Clase: «Persona»
• Atributos: nombre, edad, género
• Métodos: caminar, hablar, comer
• Objeto 1: «Juan»
• Atributos: nombre = «Juan», edad = 25, género =
«masculino»
• Métodos: caminar(), hablar(), comer()
• Objeto 2: «María»
• Atributos: nombre = «María», edad = 30, género =
«femenino»
• Métodos: caminar(), hablar(), comer()
En este ejemplo, «Persona» es la clase que define los atributos y métodos
comunes a todos los objetos de tipo persona. «Juan» y «María» son dos objetos
diferentes creados a partir de la clase «Persona», cada uno con sus propios
valores en los atributos.
La diferencia entre una clase y un objeto radica en que la clase es la definición
abstracta y el objeto es la instancia concreta de esa definición. Las clases se
utilizan para crear objetos y definir su comportamiento.
3. ¿Cómo se realiza la encapsulación en la Programación Orientada a
Objetos?
La encapsulación es uno de los principios fundamentales de la Programación
Orientada a Objetos (POO). Se refiere a la idea de ocultar los detalles internos de
un objeto y proporcionar acceso controlado a sus propiedades y métodos.
En POO, la encapsulación se logra utilizando modificadores de acceso,
como public, private y protected. Estos modificadores determinan quién puede
acceder a los miembros de una clase.
Por ejemplo, si tenemos una clase «Persona» con una propiedad «nombre»,
podemos declararla como private para que solo se pueda acceder a ella desde
dentro de la propia clase. Esto evita que otros objetos puedan modificar
directamente el valor de la propiedad.
4. ¿Cuál es la importancia de la herencia en la Programación Orientada a
Objetos?
La herencia es uno de los conceptos fundamentales en la Programación Orientada
a Objetos (POO). Permite la creación de clases que heredan atributos y métodos
de una clase base, conocida como superclase o clase padre. Esto tiene varias
ventajas y beneficios en el desarrollo de software, ya que permite reutilizar código
y facilita la organización y estructura del programa.
Al utilizar la herencia, es posible crear nuevas clases que hereden las
características de una clase existente, y luego agregar o modificar dichas
características según sea necesario. Esto evita la repetición de código y promueve
la modularidad, ya que las clases pueden agruparse de acuerdo a su
funcionalidad.
La herencia también permite establecer relaciones entre las clases, lo que facilita
la comprensión y el mantenimiento del código. Al heredar de una clase base, las
clases derivadas pueden acceder a sus atributos y métodos, lo que simplifica el
desarrollo y evita la duplicación de código.
Además, la herencia permite la creación de jerarquías de clases, donde una clase
puede tener varias subclases que heredan de ella. Esto es especialmente útil para
modelar situaciones en las que existen diferentes niveles de abstracción o
clasificación.
• Reutilización de código: La herencia permite aprovechar el código
existente en una clase base, evitando tener que escribirlo
nuevamente en las clases derivadas.
• Organización y estructura del programa: Al agrupar las clases en
jerarquías de herencia, se puede mejorar la organización y la
estructura del programa, lo que facilita su mantenimiento y
escalabilidad.
• Modularidad: Al dividir el programa en clases más pequeñas y
especializadas, se puede lograr una mayor modularidad, lo que
facilita la comprensión y el desarrollo del software.
• Flexibilidad: Al heredar de una clase base, las clases derivadas
pueden agregar o modificar comportamientos según sea necesario,
lo que brinda flexibilidad y adaptabilidad al programa.
La herencia es un concepto fundamental en la Programación Orientada a Objetos
que permite la reutilización de código, la organización y estructura del programa, la
modularidad y la flexibilidad. Utilizar la herencia de manera adecuada puede
contribuir a un desarrollo de software más eficiente y mantenible.