Catto / Mapa de Temas · Informática II 2do nivel
Informática II · 120 h · Contenido 7 de 8

Introducción a un lenguaje avanzado

Después de C, un lenguaje con objetos permite pensar en piezas que se arman entre sí. No es una moda: es la manera de que un proyecto de diez mil líneas siga siendo comprensible.

Objetos Clases Encapsulamiento Excepciones Bibliotecas

01Por qué no alcanza con funciones

En C un programa crece como una lista de funciones que se pasan estructuras. Funciona hasta que el proyecto llega a unas miles de líneas y aparecen tres problemas: cualquiera puede tocar cualquier campo, el mismo dato se valida en veinte lugares, y agregar un caso obliga a buscar todos los if desperdigados.

Las tres ideas que resuelven eso
  • Encapsulamiento. Los datos y las operaciones que los tocan viven juntos, y desde afuera sólo se ve lo que se decidió mostrar. Si el estado sólo se cambia por métodos, siempre es válido.
  • Herencia. Una clase parte de otra y agrega o cambia lo que necesita, sin repetir lo común.
  • Polimorfismo. Se llama al mismo método sobre objetos distintos y cada uno hace lo suyo. Es lo que permite agregar un instrumento nuevo sin tocar el código que los usa.

No es una moda ni una obligación: es una manera de que un proyecto de diez mil líneas siga siendo comprensible. Para un firmware de doscientas líneas, C y una estructura siguen siendo la respuesta correcta.

02De la estructura a la clase

En CEn C++ o Python
struct Canal con sus camposLa clase, con los mismos campos privados
canal_init(&c, ...)El constructor
canal_leer(&c)Un método: el objeto es el primer parámetro implícito
canal_liberar(&c)El destructor, o el bloque with
Un puntero a función en la estructuraUn método virtual
class Canal:
    def __init__(self, nombre, escala):
        self.nombre = nombre
        self._escala = escala # el guion bajo dice «no me toques»

    def leer(self):
        return self._crudo() * self._escala

Ese self explícito de Python es el mismo this implícito de C++ y el mismo puntero a la estructura que se pasaba a mano en C. Cambia la sintaxis, no el mecanismo.

Laboratorio · herencia y polimorfismo

El mismo código llama a medir() sobre objetos distintos. Elegí cuál es y mirá qué implementación se ejecuta.

03El despacho dinámico

Cuando se llama a un método sobre un objeto, el lenguaje tiene que decidir cuál de las implementaciones ejecutar. Si esa decisión se toma al compilar, es despacho estático; si se toma al ejecutar, mirando el tipo real del objeto, es dinámico, y es lo que hace posible el polimorfismo.

for equipo in banco: # multímetro, osciloscopio, fuente…
    print(equipo.describir())  # cada uno responde lo suyo

El bucle no sabe ni le importa qué hay adentro de la lista. Agregar un instrumento nuevo no obliga a tocarlo: alcanza con que la clase nueva implemente los mismos métodos. Eso es lo que se gana.

Cómo está hecho por dentro

En C++, cada clase con métodos virtuales tiene una tabla de funciones virtuales, y cada objeto guarda un puntero a la tabla de su clase. Llamar a un método virtual es leer ese puntero, buscar la entrada y saltar: dos indirecciones más que una llamada común. En Python es todavía más dinámico —se busca el nombre en un diccionario— y por eso es más flexible y más lento.

04Tipos abstractos y excepciones

Un tipo abstracto de datos se define por lo que se puede hacer con él, no por cómo está hecho. Una pila es «apilar, desapilar y ver el tope», sin importar si adentro hay un arreglo o una lista enlazada. La biblioteca estándar es justamente eso: contenedores probados que ya no hay que escribir.

NecesidadC++Python
Secuencia que crecestd::vectorlist
Buscar por clavestd::map, unordered_mapdict
Sin repetidosstd::setset
Cola de doble puntastd::dequecollections.deque
Memoria que se libera solaunique_ptr, shared_ptrRecolector de basura

Excepciones

En C, una función informa el error devolviendo un código que casi nadie verifica. Las excepciones separan el camino normal del camino de error:

try:
    v = instrumento.medir()
except TimeoutError:
    registrar("el equipo no respondió")
finally:
    instrumento.cerrar() # esto corre pase lo que pase

Tres reglas: atrapar sólo lo que se sabe manejar —un except vacío esconde errores de programación—, liberar siempre con finally o con with, y no usar excepciones para el flujo normal, que son caras y confunden.

05Cuál usar en electrónica

TrabajoHerramienta razonable
Firmware de microcontrolador chicoC, y C++ sin excepciones ni asignación dinámica
Firmware grande, con capasC++ moderno: clases, plantillas, constexpr
Herramienta de laboratorio, interfaz, análisisPython, por lo rápido que se escribe
Procesar mediciones y graficarPython con NumPy y Matplotlib
Lo que tiene que volarC o C++, o la parte crítica en C llamada desde Python

La combinación más útil para un electrónico es saber los dos: C o C++ para el equipo y Python para todo lo que lo rodea —automatizar el banco, procesar las mediciones, armar el informe—. No compiten: se usan en capas distintas del mismo proyecto.

06En el laboratorio

Actividad 1 · La misma cosa, dos veces

Implementar una pila en C con estructura y funciones, y en C++ o Python como clase. Comparar cuántas formas hay de usarla mal en cada caso.

Actividad 2 · Un banco de instrumentos

Definir una clase base Instrumento con conectar, medir y describir, y tres derivadas. Recorrer una lista mezclada llamando a los mismos métodos, y después agregar una cuarta clase sin tocar el bucle.

Actividad 3 · Errores que no se pueden ignorar

Escribir una función que lea el puerto serie y lance excepción si el equipo no responde. Verificar con finally que el puerto queda cerrado incluso cuando falla.

07Errores frecuentes

  • Hacer clases para todo. Si no hay estado que cuidar, una función alcanza.
  • Herencia profunda. Cuatro niveles son más difíciles de seguir que un poco de repetición.
  • Exponer todos los atributos y perder la única garantía que daba el encapsulamiento.
  • Atrapar Exception y seguir como si nada, ocultando errores reales.
  • Usar excepciones para el flujo normal, como salir de un bucle.
  • Suponer que Python es lento en todo: lo lento es el bucle escrito a mano; con NumPy el cálculo corre en C.

08Autoevaluación

¿Qué es el encapsulamiento y qué garantiza?

Guardar juntos los datos y las operaciones, y exponer sólo lo necesario. Garantiza que el estado sólo cambia por caminos validados.

¿Qué permite el polimorfismo que sin él costaría mucho?

Agregar un tipo nuevo sin tocar el código que lo usa: el bucle que recorre la lista de instrumentos sigue igual.

¿Cómo resuelve C++ una llamada a un método virtual?

Por la tabla de funciones virtuales: el objeto guarda un puntero a la tabla de su clase y la llamada salta a la entrada que corresponde, ya en ejecución.

¿Por qué está mal except: pass?

Porque atrapa todo, incluidos los errores de programación, y los esconde. Hay que atrapar sólo las excepciones que se saben manejar.

¿Qué hace finally?

Ejecuta ese bloque haya o no excepción: es donde se cierra el puerto, el archivo o la conexión.

¿Conviene usar objetos en un microcontrolador de 2 kB de RAM?

Clases simples sí; excepciones y asignación dinámica, no. La herramienta se elige por el problema, no por costumbre.

09Para ampliar

  • Bjarne Stroustrup. A Tour of C++. 3.ª ed., Addison-Wesley, 2022. El C++ moderno en doscientas páginas, escrito por su autor.
  • Mark Lutz. Learning Python. 5.ª ed., O'Reilly, 2013. Completo y cuidadoso con el modelo de objetos del lenguaje.
  • Erich Gamma y otros. Design Patterns. Addison-Wesley, 1994. Los patrones clásicos. Conviene leerlo después de haber sufrido los problemas que resuelven.
  • Robert C. Martin. Clean Code. Prentice Hall, 2008. Discutible en varias cosas, pero instala la pregunta correcta: si esto se entiende dentro de un año.
Desarrollo del contenido «Introducción a un lenguaje avanzado» de Informática II (segundo nivel), según el diseño curricular de Ingeniería Electrónica, Plan 2023 — Ordenanza N° 1849 del Consejo Superior de la UTN. Volver al Mapa de Temas · catto.ar