Está en la página 1de 16

UNIDADEDUCATIVA FISCAL

“LUXEMBURGO”
NOMBRE: Romero Sebastián
CURSO: 2DO “K”
FECHA:20 DE MARZO DEL 2023

Programación Orientada a Objetos


¿Qué es la Programación Orientada a Objetos?
La Programación Orientada a Objetos (POO) es un paradigma de programación,
es decir, un modelo o estilo de programación que nos brinda alguna orientación
sobre cómo trabajar con él. Se basa en términos de clases y objetos. Esta clase de
programación se utiliza para estructurar un programa en piezas básicas y
reutilizables de planos de código (clases) para crear instancias específicas de
objetos.

A lo largo de la historia han surgido diferentes paradigmas de programación. Los


lenguajes secuenciales como COBOL o los lenguajes procedimentales como
Basic o C son más lógicos que los orientados a datos. Otros, más modernos,
como Java, C# y Python, utilizan paradigmas para conceptualizar programas,
siendo la programación orientada a objetos la más común.

Con el paradigma de la programación orientada a objetos, tendemos a dejar de


centrarnos en la lógica pura del programa y comenzamos a pensar en términos
de objetos, que es la base de este paradigma. Esto nos ayuda mucho en sistemas
grandes, porque en lugar de pensar en la funcionalidad, pensamos en las
interacciones o interconexiones de los diversos elementos del sistema.

Un programador diseña un programa organizando piezas de información y


comportamiento asociados con una plantilla llamada clase. Luego, los objetos
privados se generan a partir de la plantilla de clase. Toda la programación del
programa se realiza mediante la interacción de diferentes objetos entre sí para
crear un programa más grande.
¿Para qué sirve?

La programación dirigida a objetos hace que el código sea reutilizable,


organizado y fácil de mantener. Sigue el enfoque DRY (Don't Repeat Yourself)
para el desarrollo de programas que utilizan muchos programadores, para evitar
la duplicación de código y producir programas eficientes tal como están.
Además, evita la entrada de datos no deseados o la exposición de código
propietario a través de la encapsulación y la abstracción, que analizaremos en
detalle más adelante.

Clases, objetos e instancias

¿Cómo se generan los programas orientados a objetos? Resumiendo mucho,


consiste en crear clases y producir objetos a partir de estas clases. Las clases
forman el modelo a partir del cual se construyen los datos y el comportamiento.

El primer y más relevante criterio OOP es la exclusión entre clases y objetos.

Las clases son plantillas. Define en general cómo será un objeto del tipo
especificado. Por ejemplo, una clase para representar animales podría llamarse
'animal' y tener un orden de atributos, como 'nombre' o 'edad' (que generalmente
son propiedades), y un conjunto de comportamientos que podría tener esa clase.,
como walk o ingest, y que se implementan en paralelo como procedimientos de
clase (funciones).

Un ejemplo simple de un objeto, como mencionamos antes, podría ser un


animal. Un animal tiene una edad, por lo que creamos un nuevo atributo 'edad', y
puede envejecer, por lo que definimos un nuevo procedimiento. Datos y lógica.
En otras palabras, lo que se define en varios programas como una definición de
clase, que es una definición universal y común de varios objetos.

Programación con directivas de objetos

Con las clases tienen la posibilidad de generar instancias de un objeto, todas con
sus atributos definidos de forma independiente. Con esto podemos producir un
gatito llamado Paco, de 3 años, y otro animal, esta clase de perro y llamado
Pancho, de 4 años. Ambos todavía están definidos por la clase de animal, pero
son 2 ejemplos diferentes. Por lo tanto, llamar a su procedimiento puede tener
resultados diferentes. Los dos comparten lógica, pero cada uno tiene su propio
estado.

Todo lo anterior, junto con los principios que veremos más adelante, son
herramientas que pueden ayudarnos a escribir un código mejor, más limpio y
reutilizable.

Comienzos de la programación orientada a objetos

Encapsulación
La encapsulación incluye toda la información básica de un objeto en el interior y
expone solo la información seleccionada en el exterior.

Esta propiedad le permite agrupar propiedades o atributos con entradas privadas


y comportamientos o procedimientos que representan entradas públicas en una
clase para garantizar que la información del objeto esté oculta del exterior.

Cada encapsulación de objetos es responsable de su propia información y de su


propio estado. La única forma en que esto se puede cambiar es a través de un
procedimiento en el propio objeto. Por lo tanto, los atributos internos de un
objeto no deben ser accesibles externamente y solo se pueden cambiar llamando
a la función correspondiente. Esto mantiene el estado a salvo del uso indebido y
condiciones ilegibles.

Usaremos un automóvil como ejemplo para ilustrar la encapsulación. Los


automóviles comparten información pública a través de las luces de freno o las
señales de giro (interfaz pública). Por otro lado, hay una interfaz interna que
podría ser el mecanismo de conducción del automóvil escondido debajo del
capó. Una vez que haya conducido su automóvil, debe mostrar a otros
conductores lo que está haciendo, pero no revele sus datos personales sobre el
tipo de combustible o la temperatura del motor. Grandes cantidades de datos
pueden confundir a otros conductores.

Existen tres niveles de acceso para el encapsulamiento, los cuales son:


Público (Public): Todos pueden acceder a los datos o métodos de una clase que
se definen con este nivel, este es el nivel más bajo, esto es lo que tú quieres que
la parte externa vea.

Protegido (Protected): Podemos decir que estás no son de acceso público,


solamente son accesibles dentro de su clase y por subclases.

Privado (Private): En este nivel se puede declarar miembros accesibles sólo para
la propia clase.

Los siguientes métodos permiten interactuar con atributos protegidos o privados:


setters: permiten asignar el valor a un atributo
getters: permiten leer el valor de un atributo
La estructura de un método setter es:

La estructura de un método getter es:

Ejemplo:

Realizar un programa que cree un objeto que tenga un atributo de tipo privado,
así como el método setter y el método getter para ese atributo. El programa
deberá escribir un número en el atributo privado y mostrar el número en pantalla
accediendo al atributo.
Código:
Abstracción

Abstracción significa que el cliente interactúa solo con atributos y


procedimientos seleccionados del objeto y utiliza herramientas muy
simplificadas para acceder al objeto complejo.

En la programación orientada a objetos, los programas suelen ser muy grandes y


los objetos se comunican mucho entre sí. El término abstracción hace posible
mantener un gran tamaño de código donde pueden ocurrir varios cambios todo el
tiempo.
Así, la abstracción se basa en expresar dificultad para usar cosas básicas. Los
objetos y las clases representan el código subyacente, ocultando detalles
complejos del cliente. Entonces significa una extensión de la encapsulación.
Siguiendo con el ejemplo del automóvil, no es necesario conocer todos los
detalles de cómo funciona un motor para conducirlo.

Herencia

La herencia define interacciones jerárquicas entre clases para que los atributos y
procedimientos comunes puedan reutilizarse. Las clases principales extienden
atributos y comportamientos a las clases secundarias. Al definir atributos y
comportamientos básicos en una clase, se pueden generar clases secundarias que
amplían la funcionalidad de la clase principal y agregan atributos y
comportamientos adicionales.

Volviendo a nuestro ejemplo de animales, podemos usar una sola clase de


animal y agregar un atributo de tipo de animal que especifique el tipo de animal.
Diferentes tipos de animales requieren diferentes procedimientos. Por ejemplo,
las aves necesitan poner huevos y los peces necesitan nadar. Incluso si los
animales tienen procedimientos comunes como la locomoción, su uso requerirá
muchas declaraciones "si" para garantizar un comportamiento de locomoción
adecuado. Por ejemplo, las ranas saltan, pero las serpientes se deslizan.
Comenzar la herencia resuelve este problema.

Polimorfismo
El polimorfismo se basa en el diseño de objetos para compartir el
comportamiento. Esto le permite manejar una amplia variedad de objetos
posibles. Esta es la capacidad de exponer la misma interfaz a diferentes métodos
subyacentes o tipos de datos. Mediante el uso de la herencia, un objeto puede
anular el comportamiento principal compartido con un comportamiento
secundario específico. El polimorfismo permite que el mismo procedimiento se
comporte de manera diferente de dos maneras: desaprobación del procedimiento
y sobrecarga del procedimiento.

Mucho se construye alrededor de los comienzos de la programación orientada a


objetos. Por ejemplo, los Principios SOLID (patrones de diseño) son recetas que
se utilizan para problemas comunes que se descubren y repiten en varios
proyectos.

Ejemplo:

Realizar un programa que cree una clase con 3 atributos de tipo int y un método
para mostrarlos en pantalla. Posteriormente crear una clase hija que deberá
incluir un nuevo atributo de tipo int y sobrescribir el método para mostrar los 4
atributos.
Código:
Beneficios de la Programación Orientada a Objetos
Reutilización de código.

Convierta cosas complejas en diseños básicos reproducibles.

Prevención de la duplicación de código.

Esto permite el trabajo en equipo debido a la encapsulación, ya que minimiza la


posibilidad de funcionalidad duplicada cuando varias personas trabajan en el
mismo objeto al mismo tiempo.

Dado que la clase está bien organizada, le permite corregir errores en diferentes
lugares del código.

Protege la información mediante encapsulación, ya que a los datos de un objeto


solo se puede acceder a través de funciones y procedimientos privados.

La abstracción nos permite crear sistemas más complejos de una manera más
simple y estructurada.

Desventajas de la Programación Orientada a Objetos

El modelo de programación orientada a objetos ha sido criticado por los


desarrolladores por múltiples razones. La mayor preocupación es que la
programación orientada a objetos hace demasiado hincapié en el componente de
datos del desarrollo de software y no se centra lo suficiente en la computación o
los algoritmos. Además, el código OOP puede ser más complicado de escribir y
tardar más en compilarse.

Los métodos alternativos a la programación orientada a


objetos incluyen:

programación funcional
programación estructurada
programación imperativa
Los lenguajes de programación más avanzados brindan a los desarrolladores la
opción de combinar estos modelos

Ejemplo de POO
Para este primer ejemplo, vamos a reescribir un juego escrito de forma
procedimental a programación orientada por objetos. El juego se trata de
adivinar el número secreto, veamos la implementación procedimental:
num_attempts = 0
number = rand(1..10)
found = false
until found
print "Adivina el número de 1 a 10 que estoy pensando: "
guess = gets.chomp.to_i

if guess == number
puts "Muy bien! Lo lograste en #{num_attemps} intentos!"
found = true
else
puts "Lo siento! No es el número, intenta nuevamente."
num_attempts += 1
end
end
Este código empieza inicializando las variables que vamos a utilizar:
num_attempts y number. También creamos una variable found que nos va a
indicar si ya se encontró la respuesta.
Después iteramos mientras que found sea false. En cada iteración le pedimos al
usuario que adivine el número y si es correcto termina el juego (cambiamos
found a true para que termine la iteración). De lo contrario, incrementamos el
número de intentos.
En este momento nuestro juego está muy acoplado a la línea de comandos y
sería muy difícil adaptarlo a otros ambientes como una aplicación de escritorio o
Web. Lo que vamos a hacer con programación orientada a objetos es separar el
juego de la interfaz de usuario.
Primero vamos a crear una clase Game que se encargue de la lógica del juego.
Crea un nuevo archivo llamado game.rb y escribe lo siguiente:
class Game
attr_reader :num_attempts, :found
def initialize
@number = rand(1..10)
@num_attempts = 0
@found = false
end

def attempt(guess)
if guess == number
@found = true
else
@num_attempts += 1
end
end
end
Nuestra clase Game va a tener 3 métodos públicos: attempt, num_attempts y
found (los últimos dos los crea el attr_reader). El constructor se va a encargar de
inicializar los atributos, incluyendo el número que se va a adivinar.
Ahora, si quisiéramos utilizar nuestro juego en otro ambiente lo podríamos hacer
fácilmente, sería cuestión de copiar esta clase. Ahora veamos cómo lo
utilizaríamos desde una interfaz de línea de comando (como lo hicimos
anteriormente). Reemplaza el contenido de guess_number.rb con el siguiente
código:
require "./game"

game = Game.new
until game.found
print "Adivina el número de 1 a 10 que estoy pensando: "
guess = gets.chomp.to_i
game.attempt(guess)
if game.found
puts "Muy bien! Lo lograste en #{game.num_attemps} intentos!"
else
puts "Lo siento! No es el número, intenta nuevamente."
end
end
Veamos qué hace este código. El primer paso es importar el archivo con la clase
Game. Luego creamos una nueva instancia de Game e iteramos mientras que el
número no haya sido encontrado. En cada iteración utilizamos nuestra case
Game para realizar los intentos y verificar si ya fue encontrado.
Código más fácil de probar
Supongamos que queremos crear pruebas automatizadas para nuestra clase
Game. Lo que queremos probar es que:
Al crear un nuevo juego el número de intentos es 0 y no se ha encontrado el
número.
El número de intentos (num_attempts) se incremente correctamente.
found se actualiza a true cuando sea adivina el número.
Crea un archivo game_test.rb y escribe lo siguiente:
require "minitest/autorun"
require "./game"

class GameTest < Minitest::Test


def setup
@game = Game.new
end
def test_constructor_initializes_num_attempts_and_found
assert_equal 0, @game.num_attempts
assert_not @game.found
end

def test_increments_num_attemps_on_failed_attempts
end

def test_found_is_updated_when_number_is_guessed
end
end
Tenemos un problema para implementar las dos últimas pruebas. Actualmente el
número se genera de forma aleatoria. ¿Cómo podemos saber cuál es el número?
Vamos a hacer uso de la programación orientada a objetos para solucionar este
problema. Primero, vamos a crear una clase RandomNumberGenerator con un único
método generate que retorne un número aleatorio. Crea una nueva clase
random_number_generator.rb y escribe lo siguiente:
class RandomNumberGenerator
def generate
rand(1..10)
end
end
Ahora, vamos a cambiar Game para que reciba un argumento en el constructor, que
por defecto va a ser una nueva instancia de RandomNumberGenerator:
require './random_number_generator.rb'

class Game
attr_reader :num_attempts, :found
# recibe un objeto que responda a generate, por defecto va a ser
RandomNumberGenerator
def initialize(number_generator = RandomNumberGenerator.new)
@number = number_generator.generate
@num_attempts = 0
@found = false
end

...
end
¿Cuál es la ventaja de este cambio? Que para las pruebas podemos crear un nueva
clase que nos devuelva un número fijo para poder probar fácilmente. Al constructor de
Game no le importa qué objeto le llegue como argumento siempre y cuando responda
al método generate. A esto se le conoce en el mundo de la programación como duck
typing.
Crea un nuevo archivo llamado fixed_number_generator.rb con el siguiente contenido:
class FixedNumberGenerator
def initialize(number)
@number = number
end

def generate
@number
end
end
Esta clase recibe un argumento en el constructor, el número que se va a generar. El
método generate siempre retorna el número que le pasamos en el constructor. De esta
forma vamos a saber cuál es el número que se debe adivinar.
Ahora podemos utilizar nuestro FixedNumberGenerator para implementar nuestras
pruebas:
require "minitest/autorun"
require "./fixed_number_generator"
require "./game"

class GameTest < Minitest::Test


def setup
# el número a adivinar siempre va a ser 5
generator = FixedNumberGenerator.new(5)
@game = Game.new(generator)
end

def test_constructor_initializes_num_attempts_and_found
assert_equal 0, @game.num_attempts
assert_not @game.found
end

def test_increments_num_attemps_on_failed_attempt
@game.attempt(4)

assert_not @game.found
assert_equal 1, @game.attempts
end

def test_found_is_updated_when_number_is_guessed
@game.attemp(5)

assert @game.found
end
end
Hemos utilizado la programación orientada a objetos para dos cosas:
Separar la lógica del juego de la forma en que se le muestra al usuario.
Hacer nuestro código más fácil de probar.

También podría gustarte