Está en la página 1de 7

UNIVERSIDAD NACIONAL MULTIDISCIPLINARIA

“RICARDO MORALES AVILES”

UNIDAD I: Elementos introductorios al estudio de los lenguajes de programación.

Contenido:

1. El concepto de tipo, diferentes tipos de datos y su representación. Chequeo estático y


dinámico de tipos.

¿Qué es un tipo?

• Conjunto de valores o "elementos de un conjunto", más...


• Conjunto de operaciones que puedo realizar sobre ellos.

Ej:

• Números: 1, 2, pi,
• Los puedo: sumar, restar, dividir, etc..

¿Y en objetos?

Los "valores" son los objetos, las "operaciones" son los mensajes. En objetos tenemos eso,
objetos y mensajes.
Creemos que para pensar las implicancias del concepto de tipo en objetos, conviene pensar a
los tipos más desde las operaciones que como conjuntos de valores.
Por lo tanto, vamos a asociar tipos con conjuntos de mensajes. Vamos a ver que en distintos
lenguajes la definición y validación de tipos tienen distintas características.

La primer idea es matchear un tipo con una clase.


Pero no es la única idea de tipos en OOP. Porque un objeto puede implementar varios tipos.

¿Para qué sirven los tipos?

Para muchas cosas.

A los programadores nos ayuda a ordenarnos las ideas. Asociando tipos con conjuntos de
mensajes, podemos entender qué tipo va a tener el objeto asociado a una variable, y por lo
tanto qué mensajes tiene sentido enviarle. También entendemos qué tipo esperamos del
objeto que va a llegar como parámetro a un método.
Si tengo este código Scala

#Familia
var elPerro: Perro

#Cuidador
def administrar(p: Perro) = {
...
}

entonces sé que

Ing. Govinda Romero Lenguajes de Programación Pag. 1


• dentro de los métodos de Familia al objeto referenciado por elPerro les puedo
enviar los mensajes reproducirse, caminar y ladrar,
• dentro del método adminstrar en Cuidador, al objeto que me llega por el
parámetro p le puedo enviar esos mensajes
• el objeto que paso por parámetro al enviarle adminsitrar a un Cuidador , seguro,
tiene que poder entender estos mensajes. En realidad, como está el código puesto,
tiene que ser un Perro. Estas dos cosas ¿son lo mismo?

A los lenguajes de programación le sirve la información de tipos para poder atajar posibles
errores antes de que ocurran, estos son los chequeos estáticos de los que vamos a hablar
también.
Un ejemplo que ya sabemos: en Scala, el método

#Cuidador
def administrar(p: Perro) = {
p.nadar
}

no compila, porque el lenguaje se puede dar cuenta de que el objeto que llegue por el
parámetro, dado que es un Perro, no puede garantizarse que entienda el mensaje nadar.
Este es el error de tipos típico en objetos: le envío un mensaje a un objeto que no lo
entiende.

A los entornos de desarrollo les sirve para asistir al escribir un programa. Si en Eclipse
estoy escribiendo el método

#Cuidador
def administrar(p: Perro) = {
p.
}

y después del "p." pulso Ctrl-Space, me abre una ventanita con las opciones de los mensajes
que le puedo enviar a p. Eso lo puede hacer porque sabe que es un Perro, si no ¿cómo haría?

Subtipado
Un subtipo es ... lo que nos imaginamos a partir de pensar en clases / subclases, o interfaces /
subinterfaces.
Van distintas definiciones de cuándo vale decir que B es subtipo de A.

• desde las operaciones: si todos los mensajes que le puedo enviar a un (objeto con el
tipo) A, seguro que también se los puedo enviar a un (objeto con el tipo) B.
• desde los usos: si a cualquiera que le puedo enviar un A, acepta un B.
• desde la concepción: si de cualquier B puedo decir que es un A.

Pensar en Mamifero y Perro, en cualquiera de las tres definiciones, da que Perro es subtipo de
Mamifero.

Para qué me sirve ... básicamente para habilitar polimorfismo. Si a un método que espera
un Mamifero no le puedo enviar un Perro o un Delfin ... kaput polimorphismus.

Ing. Govinda Romero Lenguajes de Programación Pag. 2


En realidad este es el tipo de polimorfismo típico de los objetos, el (justamente) polimorfismo
por subtipado. Los que conocen programación funcional vieron otras formas de lograr
polimorfismo.

Problemas de la relación de subtipado

Pensemos en clases que modelan Cuadrados y Rectángulos. ¿Cuál es la relación entre esos
clases? ¿Alguna resulta ser subtipo de otra?

Si entendemos herencia como una relación “es un”, es cierto que un cuadrado “es
un” rectángulo. Siguiendo ese principio Cuadrado debería ser un subtipo de Rectángulo.

Sin embargo, los Rectángulos podrían tener métodos inadecuados para un Cuadrado, por
ejemplo stretch: (Integer × Integer) -> Void.
El método stretch recibe dos coeficientes y transforma a un rectángulo estirándolo en función
de esos coeficientes. Esa operación no puede ser realizada por un Cuadrado.

Este problema se produce en muchos lenguajes orientados a objetos, ya que las ideas de
clase y herencia concentran muchas de las herramientas de esos lenguajes:

1. Las clases son la única forma de definir el comportamiento de un objeto.


2. Las clases son la única forma de crear objetos.
3. Las clases son la única forma de definir tipos.
4. La herencia es la única forma de compartir comportamiento que no requiere una
codificación específica.
5. La herencia es la única forma de definir subtipos.

Y para colmo la herencia está restringida a "herencia simple", es decir, cada clase puede tener
una única superclase.

En algunos lenguajes como Java, la presencia de interfaces relaja un poco las ideas 3 y 5; sin
embargo las clases y la herencia aún tienen una importancia grande. Sin duda es una mejora,
pero todavía es una mejora pequeña.

Características de un Sistema de Tipos

Generalmente escuchamos (y NOS escuchamos) hablar de que tal o cual lenguaje es "tipado"
y tal otro no. O que es "débilmente tipado", en contraposición a "fuertemente" tipado.
También hablamos de lenguajes "estáticos", lenguajes "dinámicos". Y hasta de
lenguajes con o sin checkeos (de tipos).

Si pensamos que un lenguaje se puede definir en base a una única de estas categorías,
entonces estamos equivocados. Porque cada una de ellas describe diferentes características
de un lenguaje.
Por lo tanto, a veces incluso confundimos las categorías y decimos que un lenguaje es
dinámico, cuando en realidad queremos expresar la idea de que el los checkeos se hacen en
runtime.

La idea de esta sección es plantear a modo de sugerencia, una categorización de los

Ing. Govinda Romero Lenguajes de Programación Pag. 3


lenguajes en términos un poco más precisos. Describimos entonces los siguientes aspectos o
características de un lenguaje:

Momento del checkeo

Se refiere a la capacidad del lenguaje de verificar que una operación es válida para un objeto
dado.
Distinguimos entre estas tres opciones:

1. Chequeo estático
o Se realiza antes de la ejecución (por ejemplo, los realiza el compilador).
o Ejemplos "puros": Haskell y Scala hacen todos sus chequeos en forma
estática.
o Ejemplos "impuros": Java y C hacen chequeos en forma estática, pero esto no
es todo lo que pasa.
2. Chequeo dinámico
o Se realiza durante la ejecución.
o Al encontrarse un error de tipos durante la ejecución / evaluación, el lenguaje
lo detecta y modela.
o Un ejemplo que conocemos todos es Smalltalk. El modelo de error de tipo es
el DoesNotUnderstand.
o Otros ejemplos: Python, Ruby.
3. No chequea en ningún momento
o Al encontrarse un error de tipos durante la ejecución / evaluación, el lenguaje
no lo detecta, y las consecuencias son impredecibles.

Tipos de datos

Un tipo de datos es la propiedad de un valor que determina su dominio (qué valores


puede tomar), qué operaciones se le pueden aplicar y cómo es representado
internamente por el computador.

Todos los valores que aparecen en un programa tienen un tipo.

A continuación revisaremos los tipos de datos elementales de Python. Además de


éstos, existen muchos otros, y más adelante aprenderemos a crear nuestros propios
tipos de datos.

Números enteros
El tipo int (del inglés integer, que significa «entero») permite representar números enteros.

Los valores que puede tomar un int son todos los números enteros: ... -3, -2, -1, 0, 1, 2, 3, ...

Los números enteros literales se escriben con un signo opcional seguido por una secuencia de
dígitos:

1570
+4591
-12

Ing. Govinda Romero Lenguajes de Programación Pag. 4


Números reales
El tipo float permite representar números reales.

El nombre float viene del término punto flotante, que es la manera en que el computador
representa internamente los números reales.

Hay que tener mucho cuidado, porque los números reales no se pueden representar de
manera exacta en un computador. Por ejemplo, el número decimal 0.7 es representado
internamente por el computador mediante la aproximación 0.69999999999999996. Todas las
operaciones entre valores float son aproximaciones. Esto puede conducir a resultados algo
sorpresivos:

>>> 1/7 + 1/7 + 1/7 + 1/7 + 1/7 + 1/7 + 1/7


0.9999999999999998

Los números reales literales se escriben separando la parte entera de la decimal con un
punto. Las partes entera y decimal pueden ser omitidas si alguna de ellas es cero:

>>> 881.9843000
881.9843
>>> -3.14159
-3.14159
>>> 1024.
1024.0
>>> .22
0.22

Otra representación es la notación científica, en la que se escribe un factor y una potencia de


diez separados por una letra e. Por ejemplo:

>>> -2.45E4
-24500.0
>>> 7e-2
0.07
>>> 6.02e23
6.02e+23
>>> 9.1094E-31
9.1094e-31

Los dos últimos valores del ejemplo son iguales, respectivamente,


a 6.02×10236.02×1023 (la constante de Avogadro) y 9.1094×10−319.1094×10−31 (la masa
del electrón).

Ing. Govinda Romero Lenguajes de Programación Pag. 5


Números complejos
El tipo complex permite representar números complejos.

Los números complejos tienen una parte real y una imaginaria. La parte imaginaria es
denotada agregando una j inmediatamente después de su valor:

3 + 9j
-1.4 + 2.7j

Valores lógicos
Los valores lógicos True y False (verdadero y falso) son de tipo bool, que representa valores
lógicos.

El nombre bool viene del matemático George Boole, quien creó un sistema algebraico para la
lógica binaria. Por lo mismo, a True y False también se les llama valores booleanos. El
nombre no es muy intuitivo, pero es el que se usa en informática, así que hay que conocerlo.

Texto
A los valores que representan texto se les llama strings, y tienen el tipo str.

Los strings literales pueden ser representados con texto entre comillas simples o comillas
dobles:

"ejemplo 1"
'ejemplo 2'

La ventaja de tener dos tipos de comillas es que se puede usar uno de ellos cuando el otro
aparece como parte del texto:

"Let's go!"
'Ella dijo "hola"'

Es importante entender que los strings no son lo mismo que los valores que en él pueden
estar representados:

>>> 5 == '5'
False
>>> True == 'True'
False

Los strings que difieren en mayúsculas y minúsculas, o en espacios también son distintos:

>>> 'mesa' == 'Mesa'


False
>>> ' mesa' == 'mesa '
False

Ing. Govinda Romero Lenguajes de Programación Pag. 6


Nulo
Existe un valor llamado None (en inglés, «ninguno») que es utilizado para representar casos
en que ningún valor es válido, o para indicar que una variable todavía no tiene un valor que
tenga sentido.

El valor None tiene su propio tipo, llamado NoneType, que es diferente al de todos los demás
valores.

Tarea:
Investigar en C++ que son:

1. Funciones
2. Recursividad
3. Sobrecarga de operadores

Ing. Govinda Romero Lenguajes de Programación Pag. 7

También podría gustarte