Está en la página 1de 9

Capítulo 1. Fundamentos - Gobstones.

Tablero: contamos las filas hacia arriba, y las columnas hacia la derecha. La primera fila es la de abajo de todo, y la primera columna es la de la izquierda.
program: sección del código que declara los comandos (acciones) que queremos que la máquina realice sobre el tablero.
program {
}

Comandos primitivos o primitivas: vienen definidos por el lenguaje y nos sirven para expresar operaciones básicas:
• Mover(direccion): mueve el cabezal en el tablero en la dirección dada (Norte, Sur, Este U oeste).
• Poner(color): pone bolitas de colores (Rojo, Negro, Verde o Azul).
• Sacar(color): saca bolitas de colores
• IrAlBorde(direccion): toma una dirección, y se mueve todo lo que pueda en esa dirección, hasta llegar al borde. Es muy útil para cuando no
conocemos las condiciones de nuestro tablero.

Procedimientos: comandos que definimos nosotros, que nos sirven para expresar tareas más complejas:

procedure Poner2Rojas() {
Poner(Rojo)
Poner(Rojo)
}

Repetición simple: sirve para repetir un comando (como Mover, Poner, DibujarLineaNegra, etc) un cierto número de veces.

repeat(cantidad) {
Mover(Oeste)
}

Operadores aritméticos: + (suma), - (resta), * (multiplicación), div (se usa para dividir; por ejemplo "4 dividido 2" se escribe 4 div 2)

Alternativa condicional.
if (condicion) { acción

La condición puede ser cualquier expresión booleana (cualquier cosa que represente una "pregunta" que se pueda responder con sí o no). El sí se representa
con el valor True (Verdadero) y el no con el valor False (Falso).
La acción podrá realizarse solo cuando la condición sea verdadera.

else: significa si no. Ejecuta una serie de acciones si no se cumple la condición que pusimos en el if.

Expresiones booleanas.

• hayBolitas(color): recibe un color y retorna True o False.


• puedeMover(direccion): sirve para saber si el cabezal puede moverse en una cierta dirección. Retorna True o False.
• not

Funciones: siempre retornan un valor. Pueden retornar distintos tipos: un color, una dirección, un número o un booleano.

function nombreDeLaFuncion() {
return (…..)
}
• opuesto(dirección): nos dice la dirección contraria a la dirección que nosotros le pasemos.
• siguiente(direccion): retorna la dirección siguiente a la especificada (pensándolo en el sentido de las agujas del reloj).
• previo(direccion): retorna la dirección anterior a la especificada.
• nroBolitas(color): retorna la cantidad de bolitas de un color determinado en la posición actual.

Operadores lógicos.

• not (negación): para negar una condición se agrega la palabra clave not antes de la expresión que ya teníamos. Cualquier expresión booleana (o sea,
que devuelve True o False) se puede negar.

• && (conjunción): toma dos expresiones booleanas y devuelve True solo si ambas son verdaderas

• || (disyunción): retorna verdadero si al menos alguna de las expresiones booleanas es verdadera.

Tanto && como || pueden usarse varias veces sin la necesidad de usar paréntesis, siempre y cuando tengan expresiones booleanas a ambos lados.
Capítulo 2. Programación Imperativa - JavaScript.
Funciones: los paréntesis en el return no son necesarios y la última línea la terminamos con ;.

function doble(numero) {
return 2 * numero;
}

En JavaScript al procedimiento se lo llama función (no se escribe la palabra procedimiento). Si la función no retorna nada entonces “sería un procedimiento.” Si
la función retorna un valor entonces es una función en sí.

Funciones matemáticas.

hay que prefijarlas con Math.

Math.round: sirve para redondear un número


Math.max: sirve para implementar un tope inferior.
Math.min: sirve para implementar un tope superior.

Otra función:
tirarDado(): retorna un número al azar entre 1 y 6

Operadores matemáticos: +, - , /, *, >=, >, <,<=

Atajos.
x += y; //equivalente a x = x + y;
x *= y; //equivalente a x = x * y;
x -= y; //equivalente a x = x - y;
x++; //equivalente a x = x + 1;

Operadores que sirven para todos los tipos de datos.


• ===: nos dice si dos cosas son iguales
• !==: nos dice si dos cosas son diferentes

Operadores lógicos (booleanos).


• !(not, negación):
• &&(and, conjunción): es verdadero si todas sus proposiciones son verdaderas.
• ||(or, disyunción): es verdadero si alguna de sus proposiciones es verdadera.

xor o disyunción lógica excluyente: es verdadero si sólo una de sus proposiciones es verdadera.
No suele estar definido en los lenguajes, sin embargo, si alguna vez lo necesitás podés definirlo a mano:

function xor(a, b){


return (a && !b) || (!a && b);
}

function xor(a, b){


return a !== b;
}

Alternativa condicional

if: permite realizar una acción específica cuando se cumple una condición
if – else: permite elegir entre dos acciones diferentes (según se cumpla o no).
if – else if: permite elegir entre más de dos alternativas.

si usás adecuadamente las expresiones booleanas, ¡no es necesario utilizar esta estructura de control! En general, como regla práctica, si tenés ifs que
devuelven trues o falses, probablemente lo estás haciendo mal.

Strings (cadenas de caracteres): todos los strings están encerrados entre comillas simples o dobles (usar cualquiera).

• ===: permite comparar dos strings


• +: concatena dos strings (obtener uno nuevo que junta dos strings)
• si operamos un string y un número con +, se convierte implícitamente el número a string, y luego se concatenan (coerción)

Funciones para strings:


• longitud(unString): retorna cuan largo es un string
• comienzaCon(unString, otroString): retorna un booleano que nos dice si unString empieza con otroString
• convertirEnMayuscula(unString): convierte una palabra en mayúsculas
• imprimir(unstring): imprime por pantalla un string.

let: usar para declarar variables


Listas.

Es una estructura de datos que permite agruparlos. Podemos tener listas de booleanos, de números, de strings, de listas.

Pueden tener elementos duplicados. En este caso, la función posicion devuelve la posición de la primera aparición del elemento en la lista.
Para averiguar qué elemento está en una cierta posición, podemos usar el operador de indexación, escribiendo después de la colección y entre corchetes [] la
posición que queremos para averiguar:
mesesDelAnio[0]
"enero"
["ese", "perro", "tiene", "la", "cola", "peluda"][1]
"perro"
¡Ojo! El número que le pases, formalmente llamado índice, debe ser menor a la longitud de la lista

Funciones para listas:


• listasIguales(unArray, otroArray): retorna un booleano que nos dice si dos listas son iguales
• longitud(unStringOLista): retorna el largo de un string o una lista
• agregar(unaLista, unElemento): inserta unElemento al final de unaLista.
Este es un procedimiento que no retorna nada pero modifica a unaLista
• remover(unaLista, unElemento): quita unElemento de unaLista. En caso de que no esté, no hace nada.
Este es un procedimiento que no retorna nada pero modifica a unaLista
• posicion(unaLista, unElemento): retorna la posición en que se encuentra unElemento en unaLista (el primer elemento está en la posición 0, el
segundo en la 1, etc). Si el elemento no está en la lista, retorna -1.
• maximo(numeros): retorná el número más grande de una lista de números
• minimo(numeros): retorna el menor valor dentro de una lista de números

For...of: es una estructura de iteración. Permite recorrer los elementos de una lista
contador: variable que se incrementa cada vez que hacemos algo dentro de un for...of o solo aquellas veces que se cumpla una condición

Registros.

Los registros, al igual que las listas, son una estructura de datos porque nos permiten organizar información.

En las listas podemos guardar muchos elementos de un mismo tipo que representen una misma cosa (por ejemplo, todos números o todos strings). No existen
límites para las listas: pueden tener muchos elementos, ¡o ninguno!
En un registro vamos a guardar información relacionada a una única cosa (por ejemplo, un monumento o una persona), pero los tipos de los campos pueden
cambiar. Por ejemplo, el nombre y la ubicación de un monumento son strings, pero su año de construcción es un número.

Una lista puede ser el campo de un registro y también podemos tener una lista de registros.
Una lista puede estar compuesta por otras listas. Un registro puede estar compuesto por otros registros dentro.

funcion:
anio(fecha): nos dice el año de una fecha
Capítulo 3. Programación con Objetos - RUBY.
Definir (crear) un objeto:
module Pepita (nombre del objeto)
end

- Todo objeto definido comienza su nombre con mayúscula.


- == (operador): permite comparar por identidad a dos objetos. Ej: Pepita == Norita

Mensaje:
- Cuando queremos ejecutar un método de un objeto, vamos a enviarle un mensaje a ese objeto usando la siguiente sintaxis:
ObjetoReceptor.algun_mensaje
- Si a un objeto le enviamos un mensaje que no entiende, se produce un error.
- para que un objeto pueda mandarle mensajes a otro debe conocerlo. Por ejemplo, llamándolo por su nombre

- Cuando se envía un mensaje a un objeto, y este lo entiende, puede reaccionar de dos formas diferentes:
• Podría producir un efecto, es decir hacer algo. Se pone el signo de exclamación ! al final del mensaje. Por ej: el mensaje cantar! reproduce el
sonido del canto.
• O también podría devolver otro objeto. No se pone el signo de exclamación ! al final del mensaje. Por ej: el mensaje energia devuelve siempre
un número.

Interfaz: conjunto de mensajes que un objeto entiende.

Todas nuestras interacciones en un ambiente de objetos ocurren enviando mensajes y las operaciones aritméticas no son la excepción a esta regla.
En el caso de 2 + 3 podemos hacer el mismo análisis:
• el objeto receptor es 2;
• el mensaje es +;
• el argumento es 3.

también podemos escribirlo como un envío de mensajes convencional: 5.+6

nil: representa a "la nada" (también es un objeto).

Argumentos

Ej: Pepita.comer_alpiste! 40
40 es un argumento del mensaje, representa en este caso que vamos a alimentar a pepita con 40 gramos de alpiste. Un mensaje podría tomar más de un
argumento, separados por coma.

un mensaje queda identificado no sólo por su nombre sino también por la cantidad de parámetros que tiene: no es lo mismo comer_alpiste! que
comer_alpiste! 67 que comer_alpiste! 5, 6, son todos mensajes distintos.

Tips
• en Ruby, a veces, los paréntesis son opcionales. Por eso, cuando no sean imprescindibles los omitiremos.
• indicar los decimales con un punto (no con una coma). La coma la usamos para separar argumentos cuando tenemos más de uno.

Método:
es la descripción de qué hacer cuando se recibe un mensaje del mismo nombre. Ej:

module Pepita
def self.cantar!
end método
end

- todos los métodos que pertenezcan al mismo objeto van dentro del mismo module.

- un método puede producir uno o varios efectos (poner uno debajo del otro). Ej:

def self.comprar_libro!
@plata -= 300
@libros += 1
end

Atributos
- se escriben anteponiendo @
- son objetos que nos permiten representar una característica de otro objeto.
- Un objeto conoce a todos sus atributos por lo que puede enviarles mensajes. Ej:

module Pepita
@energia = 100

def self.volar_en_circulos!
@energia = @energia - 10
end
end
# Suma 'valor_a_sumar' a lo contenido en @algun_atributo
@algun_atributo += valor_a_sumar es igual a @algun_atributo = @algun_atributo + valor_a_sumar

# Resta 'valor_a_restar' a lo contenido en @algun_atributo


@algun_atributo -= valor_a_restar

- los atributos NO son mensajes.


- los objetos pueden tener múltiples atributos y al conjunto de estos atributos se lo denomina estado. El estado es siempre privado, es decir, solo el
objeto puede utilizar sus atributos.

Metodos de acceso o accessors:

• Método getter: devuelve el valor contenido en un atributo de nombre igual al suyo. Ej:

module Pepita
@energia = 100

def self.energia
@energia
end
end

(el método energia es el getter del atributo @energia. Sin declarar este método, no tendríamos forma de saber cuánta energía tiene Pepita desde fuera de este
mismo objeto

• Método setter: modifica el valor de un atributo. Es una de las maneras posibles de cambiar el objeto al que le enviamos mensajes. Ej:
def self.firmar_contrato!(ave)
@ave = ave
end

abs: mensaje que retorna el valor absoluto de un numero. Ej:

(-17).abs
=> 17

(1710 - 1040).abs
=> 670

Delegar
(una responsabilidad)

- Un objeto le puede enviar mensajes a otro objeto que conozca o a sí mismo.


- Para enviarse un mensaje a sí mismo se utiliza self como receptor del mensaje. Ej:

- La delegación es la forma que tenemos en objetos de dividir en subtareas: separar un problema grande en problemas más chicos para que nos
resulte más sencillo resolverlo.
A diferencia de lenguajes sin objetos, aquí debemos pensar dos cosas:
1. cómo dividir la subtarea, lo cual nos llevará a delegar ese comportamiento en varios métodos;
2. qué objeto tendrá la responsabilidad de resolver esa tarea.

En Ruby, es una convención que los mensajes que devuelven booleanos (o sea, verdadero o falso) terminen con un ?. Ej:

def self.debil?
@energia < 100
end
Alternativa condicional - if
module Pepita
def self.hacer_lo_que_quiera!
if self.debil?
self.comer_alpiste!(10)
end
end
end
if-else

module Jardinero
def self.cuidar!(planta)
if planta.necesita_agua?
3.times { self.regar! planta }
else
self.sacar_bichos! planta
end
end
end
times: es un mensaje que entienden los números que sirve para ejecutar una porción de código varias veces. En este caso regaríamos 3 veces la planta recibida
como argumento.

Condiciones anidadas:
En otras palabras, un if dentro de un if o un else. Ej:

module Docente
def self.nota_conceptual(nota)
if nota > 8
"Sobresaliente"
else
if nota > 6
"Satisfactoria"
else
"No satisfactoria"
end
end
end
end

En Ruby, podemos simplicar la manera de escribir un if dentro un else con elsif. Ej:

def self.nota_conceptual(nota)
if nota > 8
"Sobresaliente"
elsif nota > 6
"Satisfactoria"
else
"No satisfactoria"
end
end

La rutina nos define cuál debe ser la interfaz que debe respetar un objeto para poder ser utilizado

Polimorfismo

Dos objetos son polimórficos para un tercer objeto cuando este puede enviarles los mismos mensajes, sin importar cómo respondan o qué otros mensajes
entiendan.

Si dos objetos son capaces de responder a un mismo mensaje, podemos intercambiar un objeto por otro sin notar la diferencia (el tercer objeto los puede usar
indistintamente).

Es común que trabajando con objetos necesitemos forzar el polimorfismo

Crear getters y setters para un atributo.


a los métodos que solo sirven para acceder o modificar un atributo los llamamos métodos de acceso o accessors. Los setters son aquellos métodos
que establecen el valor del atributo (permiten modificar el valor). Mientras que los getters son aquellos que devuelven el valor del atributo (permiten consultar el
valor).

La convención en Ruby para estos métodos es:


• Los setters deben llevar el mismo nombre del atributo al que están asociados, agregando un = al final.
• Los getters usan exactamente el mismo nombre que el atributo del cual devuelven el valor pero sin el @.
• Aquellos getters que devuelven el valor de un atributo booleano llevan? al final.

Los atributos pueden ser leídos (atributo con getter), modificados (atributo con setter) o ambas cosas (atributo con getter y setter).

• Ejempo de setter:

#tenemos un modulo Auto con un atributo @color al cual queremos modificar


module Auto
def self.color=(un_color)
@color = un_color
end

#Para modificar el color el mensaje que se enviaria, por ejemplo, seria:


Auto.color= "rojo"

• Ejemplo de getter:

def self.color
@color
end

#El mensaje que se enviaría para consultar cual es el color del Auto:
Auto.color #esto nos retornará el último color que se haya asignado, por ejemplo "rojo"
Encapsulamiento

Si hacemos bien las cosas, quien use nuestros objetos sólo verá lo que necesite para poder interactuar con ellos. A esta idea la conocemos
como encapsulamiento, y es esencial para la separación de responsabilidades de la que veníamos hablando.
Será tarea tuya (y de tu equipo de trabajo, claro) decidir qué atributos exponer en cada objeto.

El encapsulamiento hace que cada objeto solo exponga lo necesario para interactuar con él y se reserve para su ámbito privado lo que no sea necesario
compartir.
En el caso de los atributos, esta exposición se logra implementando un getter (método que nos permite ver su valor) o un setter (método que nos permite
modificar su valor). Y que nuestro código sea entendido fácilmente por otras personas, elegimos utilizar una convención para darle nombre a estos métodos.

Referencias
En un ambiente hay muchos objetos, pero en realidad no interactuamos con ellos directamente, sino a través de referencias, que son nombres o etiquetas que
les damos a los objetos.
Para un objeto pueden existir múltiples nombres: cuando le damos uno nuevo, no estamos creando una copia del objeto ni modificándolo realmente, sino que
estamos creando una nueva referencia que apunta al objeto. Así que ¡ojo!, si compartís un objeto con otros, y lo mutás, ¡todos los que tengan una referencia al
mismo verán los cambios!
Finalmente, en objetos, todo lo que se parezca a una variable es una referencia, y hay de muchos tipos:
• variables de un programa
• variables locales de un método
• parámetros de un método
• atributos de un objeto
• y el nombre global de un objeto bien conocido.

saludo = "hola"
saludo.upcase
=> "HOLA"

despedida = "adiós"
despedida.size()
=> 5
- Declarar una variable significa agregar una nueva referencia al objeto existente, en lugar de copiarlo.
- siempre estamos enviando el mensaje al objeto a través de una referencia.
- Dos strings con el mismo contenido no necesariamente son el mismo objeto.

- equal?: mensaje que nos dice si dos objetos son el mismo. Ej:

otro_saludo = "buen día"


despedida = otro_saludo

"buen día".equal? "buen día"


=> false
==: mensaje que nos permite comparar dos objetos por equivalencia (lo contrario a identidad); lo cual se da típicamente cuando los objetos tienen el mismo
estado.
Y para que realmente compare a los objetos por su estado, vos tenés que implementar este método a mano en cada objeto que crees. Los siguientes objetos ya
la implementan:
o Listas
o Números
o Strings
o Booleanos
Colecciones

• lista de objetos: es un tipo de colección donde el orden importa y en la cual los elementos pueden repetirse. Es decir, el mismo objeto puede
aparecer más de una vez.
Por ejemplo, la lista de números 2, 3, 3 y 9 se escribe así: [2, 3, 3, 9]

• sets (conjuntos): otro tipo muy común de colecciones, los cuales tienen algunas diferencias con las listas:
o no admiten elementos repetidos;
o sus elementos no tienen un orden determinado.

consultas básicas sobre la colección

sirven para listas y sets:


push (numero): agrega un elemento a la colección
delete (numero): quita un elemento de la colección
include? (numero): permite saber si un elemento está en la colección
size: permite saber la cantidad de elementos que tiene la colección
max: en el caso de una colección de números, devuelve el más alto:
[-5, 7].max
=> 7

 push y delete, al ser evaluados, modifican la colección. Dicho de otra forma, producen un efecto sobre la lista en sí: agregan o quitan un elemento del
conjunto.
 include? y size sólo nos retornan información sobre la colección. Son métodos sin efecto.
Sirven solo para listas:
first: retorna el primer elemento de la lista
last: retorna el último elemento de la lista
index (numero): retorna la posición de un elemento en la lista
... no podemos enviárselos a un set porque sus elementos no están ordenados.

Sirve solo para sets:


to_set: transforma una lista en un set

Bloques

Los bloques son objetos que representan un mensaje o una secuencia de envíos de mensajes, sin ejecutar, lista para ser evaluada cuando corresponda. La
palabra con la que se definen los bloques en Ruby es proc.
Al bloque le enviamos el mensaje call, que le indica que evalúe la secuencia de envíos de mensajes dentro de él.

Los bloques también pueden recibir argumentos para su aplicación. Los argumentos deben estar escritos entre barras verticales | y separados por comas.
Para aplicar el bloque, se le pasan los argumentos deseados al mensaje call.

 select: mensaje que recibe un bloque con un parámetro que representa un elemento de la colección y una condición booleana como código, y lo que
devuelve es una nueva colección con los elementos que la cumplen.
La colección original no modifica al aplicar select, el select no produce efecto.
Ej:
def self.consulta_con_filter
@coleccion.select{|elemento| elemento.algo?}
end

 find: mensaje que devuelve únicamente un elemento de los que cumplan la condición de una colección. Y si ningún elemento de la colección cumple
la condición, devuelve nil, que es un objeto que representa la nada - o en este caso, que ninguno cumple la condición.

 all?: mensaje para saber si todos los elementos de una colección cumplen un cierto criterio.

 any?: mensaje para saber si algún elemento de la colección cumple cierta condición.

Mientras que select devuelve una colección y find un elemento o nil, all? y any? siempre devuelven un valor booleano: true o false.

 map: mensaje que nos permite, a partir de una colección, obtener otra colección con cada uno de los resultados que retorna un envío de mensaje a
cada elemento.
En otras palabras, la nueva colección tendrá lo que devuelve el mensaje que se le envíe a cada uno de los elementos.
Al igual que el resto de los mensajes que vimos hasta ahora, map no modifica la colección original ni sus elementos, sino que devuelve
una nueva colección.

obs: ¿qué ocurriría si el mensaje dentro del bloque en el map sí tiene efecto?
En ese caso se modificaría la colección original, pero sería un mal uso del map . Lo que nos interesa al mapear es lo que devuelve el mensaje que
enviamos, no provocar un efecto sobre los objetos.

 count: mensaje que nos dice cuántos elementos de una colección cumplen la condición.
 sum: mensaje para calcular sumatorias.
 each: mensaje que se usa cuando queremos hacer algo con cada elemento. A diferencia del map, no nos interesan los resultados de enviar el mismo
mensaje a cada objeto, sino mandarle un mensaje a cada uno con la intención de producir un efecto.
Clases
- Sirven para generalizar (agrupar) objetos que tengan el mismo comportamiento: mismos métodos y mismos atributos. Si el comportamiento no
es exactamente igual, es necesario crear una nueva clase.
- Una clase tiene métodos, atributos, pero a diferencia de en los objetos, los métodos en las clases no se preceden con la palabra self (escribir self es
optativo ).
- La clase es un objeto que nos sirve como molde para crear nuevos objetos.
- Si necesito tener muchos objetos iguales, ¡entonces quiero una clase!. Si necesito que este objeto sea único, ¡entonces puedo usar un objeto
conocido!.
Definir una clase:
class nombre

end

Instanciar:

bouba = Zombi.new
kiki = Zombi.new

Zombi es la clase
new: mensaje que entienden las clases, que crea una nueva instancia de esa clase

initialize: el mensaje initialize nos permite especificar cómo queremos que se inicialice la instancia de una clase.

def initialize metodo que permite inicializar los atributos


@algo = …
end

initialize puede recibir parámetros que especifiquen con qué valores deseamos inicializar los atributos al construir nuestros objetos. Ej:
class Planta
@altura

def initialize(centimetros)
@altura = centimetros
end
end

Esto se denomina especificar un constructor: decirle a la clase cómo querés que se construyan sus instancias.
Los constructores pueden recibir más de un parámetro.

En Ruby cuando no ponemos un receptor, entiende que el mensaje se está enviando a self, es decir a sí mismo. En el caso de la clase, el self representa el objeto
instanciado a partir de la clase que recibe el mensaje.
Es decir, que es equivalente hacer:

self.atacar!(coleccion, 15)
Que hacer:
atacar!(coleccion, 15)

Nuestros objetos también pueden crear otros objetos, enviando el mensaje new a la clase que corresponda.
Por lo tanto, los casos en los que un objeto puede conocer a otro son:
• Cuando es un objeto bien conocido, como con los que veníamos trabajando hasta ahora
• Cuando el objeto se pasa por parámetro en un mensaje (Juliana.atacar bouba, 4)
• Cuando un objeto crea otro mediante el envío del mensaje new

Herencia

• Cuando dos objetos repiten lógica, creamos una clase con el comportamiento en común. En el caso que dos clases repitan lógica deberíamos crear
una nueva clase a la cual llamamos superclase. A esta nueva clase llevaremos los métodos repetidos y haremos que las clases originales hereden de
ella. Estas subclases que heredan de la superclase solo contendrán su comportamiento particular (si el método a definir es particular va en una
subclase y si es igual para todas va en la superclase)

• El símbolo < significa "hereda de". La herencia nos permite que las subclases posean los mismos métodos y atributos que la superclase

Siempre se debe definir primero la superclase.

En Ruby no hay maneras de explicitar que una clase es abstracta (se usa class para superclase y clases). Al no haber una diferencia sintáctica, es decir,
cómo definimos estas clases, es responsabilidad de quien programa no instanciar aquellas clases que queremos que sean abstractas.

• las clases abstractas, a diferencia de las clases concretas, nunca las instanciamos. En otras palabras, no creamos objetos con esa clase, solo nos sirven
para proveer comportamiento a sus subclases.

• La Herencia nos permite heredar el comportamiento de una superclase pero redefinir aquellas cosas (métodos) que nuestras subclases hacen
distinto. Si se redefine el método, la clase va a evaluar ese código en lugar del de su superclase. Pero cuidado, si tenemos que redefinir todo
probablemente no necesitemos heredar en primer lugar.

• super: mensaje que, al utilizarlo en el método de una subclase, se evalúa el método con el mismo nombre de su superclase (super invoca el
método de su superclase).
Se usa para que una clase pueda hacer lo mismo que superclase y algo más

Excepciones.
raise “mensaje”: cuando lanzamos una excepción mediante raise mensaje estamos abortando la evaluación del método: a partir de ese momento todas las
sentencias que faltaba evaluar serán ignoradas. ¡Ni siquiera llega a retornar nada! (se provoca un error explícito que interrumpe el flujo del programa).
Sin embargo, las excepciones hacen más que sólo impedir que el resto del método se evalúe, sino que, cuando se lanzan, pueden abortar también la evaluación
de todos los métodos de la cadena de envío de mensajes.
Cuando trabajamos con excepciones el orden es importante: lanzar una excepción interrumpe el flujo de ejecución a partir de ese momento, pero no descarta
cambios realizados anteriormente: loque pasó, pasó.
Por eso, como regla práctica, siempre que querramos validar alguna situación, lo haremos siempre antes de realizar las operaciones con efecto.
si:

1. Una instancia de ClaseA le envía un mensaje mensaje1 a una instancia de ClaseB.


2. Dentro del método de mensaje1, la instancia de ClaseB le envía un mensaje mensaje2 a una instancia de ClaseC.
3. mensaje2 lanza una excepción.
4. Se aborta el método m2 y propaga la excepción, es decir, la excepción continúa a través de la cadena de envío de mensajes que nos llevó hasta ahí.
5. Se aborta también el método m1.
Esto significa que las excepciones se propagan , es decir que si le mandamos un mensaje a un objeto (o clase), y este objeto lanza una excepción, se va a
propagar (extender) automáticamente al primer objeto que envió el mensaje, ¡No hay que hacer nada para que eso suceda!
Es bastante evidente que cuando lanzás una excepción tenés que darle un mensaje. Lo que no es evidente es que:

• Por un lado, el mensaje tiene que ser claro y representativo del error.

• y por otro lado, el mensaje está destinado al programador, quien lo verá cuando haya cometido algún error.
Por ese motivo, siempre procurá lanzar excepciones con mensajes de error descriptivos.

También podría gustarte