Conceptos de POO: Atributos, Mensajes, Llamada de Métodos, Persistencia e Interfaces
Este artículo es una explicación exhaustiva de los conceptos fundamentales de POO, incluyendo atributos, mensajes, llamada de métodos, persistencia e interfaces con ejemplos prácticos.
De un Vistazo
Los conceptos de POO describen las nociones base de la programación orientada a objetos: atributos como propiedades, mensajes como comunicación, persistencia como almacenamiento de datos e interfaces como contratos.
Descripción Técnica Compacta
La programación orientada a objetos (POO) utiliza terminología específica para describir sus conceptos y estructuras.
Atributo (Attribute/Field/Property)
Un atributo es una propiedad o un estado de un objeto. Representa los datos que contiene.
Características:
- Tipo de dato: Define qué clase de datos se almacena (String, int, boolean, etc.)
- Visibilidad: public, private, protected, package
- Valor: Estado actual de la propiedad
- Ciclo de vida: Existe mientras vive el objeto
Mensaje (Message/Llamada de Método)
Un mensaje es la comunicación entre objetos. Solicita a un objeto que ejecute una acción específica.
Componentes:
- Destinatario: Objeto que recibe el mensaje
- Selector: Nombre del método a invocar
- Argumentos: Parámetros para el método
- Valor retornado: Resultado de la operación
Persistencia (Persistence)
La persistencia denota la durabilidad de los datos más allá de la ejecución del programa.
Formas de persistencia:
- Sistema de archivos: Serialización en ficheros
- Bases de datos: Relacionales o NoSQL
- Almacenamiento en la nube: Servicios externos
- En memoria: Persistencia temporal
Interfaz (Interface/API)
Una interfaz define un contrato entre componentes y especifica qué operaciones están disponibles.
Tipos de interfaces:
- Interfaces de programación: Firmas de métodos
- APIs web: Endpoints HTTP
- Interfaces de usuario: Componentes gráficos
- Interfaces de hardware: Controladores de dispositivos
Puntos Clave para Examinar
- Atributos: Propiedades o datos de objetos con visibilidad
- Mensajes: Comunicación entre objetos mediante llamada de métodos
- Llamada de métodos: Ejecución de operaciones sobre objetos
- Persistencia: Almacenamiento duradero de datos más allá de la ejecución
- Interfaces: Contratos entre componentes, APIs definidas
- Encapsulación: Datos y métodos como unidad
- Abstracción: Reducción de complejidad mediante simplificación
- Relevante en IHK: Comprensión fundamental para desarrollo con POO
Componentes Centrales
- Atributos: Propiedades de datos en objetos
- Mensajes: Comunicación entre objetos
- Métodos: Implementación del comportamiento
- Persistencia: Durabilidad de datos
- Interfaces: Contratos definidos
- Encapsulación: Agrupación de datos y métodos
- Abstracción: Reducción de complejidad
- Polimorfismo: Múltiples formas de una interfaz
Ejemplos Prácticos
1. Atributos en diferentes lenguajes
// Atributos en Java
public class Auto {
// Atributos de instancia (uno por objeto)
private String marke; // Propiedad privada
protected int baujahr; // Propiedad protegida
public double preis; // Propiedad pública
// Atributo de clase (igual para todos los objetos)
private static int anzahlAutos = 0;
// Constante
public static final int MAX_GESCHWINDIGKEIT = 250;
// Constructor para inicialización
public Auto(String marke, int baujahr, double preis) {
this.marke = marke;
this.baujahr = baujahr;
this.preis = preis;
Auto.anzahlAutos++; // Incrementar atributo de clase
}
// Getter y Setter para atributos encapsulados
public String getMarke() {
return marke;
}
public void setMarke(String marke) {
this.marke = marke;
}
public static int getAnzahlAutos() {
return anzahlAutos;
}
}
// Atributos en C#
public class Mitarbeiter
{
// Auto-Properties (sintaxis moderna)
public string Name { get; set; }
public int Alter { get; private set; } // Solo lectura desde afuera
// Property completa con validación
private double gehalt;
public double Gehalt
{
get { return gehalt; }
set
{
if (value >= 0)
gehalt = value;
else
throw new ArgumentException("Gehalt kann nicht negativ sein");
}
}
// Propiedad estática
public static string Firma { get; set; } = "TechCorp";
// Constante
public const decimal MINDESTGEHALT = 2000m;
public Mitarbeiter(string name, int alter, double gehalt)
{
Name = name;
Alter = alter;
Gehalt = gehalt;
}
}
# Atributos en Python
class Person:
# Atributo de clase
anzahl_personen = 0
def __init__(self, name, alter):
# Atributos de instancia
self.name = name # Público
self._alter = alter # Protegido (convención)
self.__geheim = "data" # Privado (Name Mangling)
Person.anzahl_personen += 1
# Property para acceso encapsulado
@property
def alter(self):
return self._alter
@alter.setter
def alter(self, wert):
if wert >= 0:
self._alter = wert
else:
raise ValueError("Alter kann nicht negativ sein")
# Método estático
@staticmethod
def get_anzahl_personen():
return Person.anzahl_personen
2. Mensajes y llamadas de métodos
// Mensajes entre objetos
public class Bankkonto {
private double kontostand;
private String kontonummer;
public Bankkonto(String kontonummer, double startbetrag) {
this.kontonummer = kontonummer;
this.kontostand = startbetrag;
}
// Método para recibir mensajes
public void einzahlen(double betrag) {
if (betrag > 0) {
this.kontostand += betrag;
System.out.println("Einzahlung: " + betrag + "€, neuer Kontostand: " + kontostand + "€");
}
}
public boolean abheben(double betrag) {
if (betrag > 0 && kontostand >= betrag) {
kontostand -= betrag;
System.out.println("Abhebung: " + betrag + "€, neuer Kontostand: " + kontostand + "€");
return true;
}
return false;
}
public double getKontostand() {
return kontostand;
}
public String getKontonummer() {
return kontonummer;
}
}
// Cliente envía mensajes a su cuenta
public class Kunde {
private String name;
private Bankkonto konto;
public Kunde(String name, Bankkonto konto) {
this.name = name;
this.konto = konto;
}
// Cliente envía mensajes a su cuenta
public void geldEinzahlen(double betrag) {
System.out.println(name + " will " + betrag + "€ einzahlen");
konto.einzahlen(betrag); // Enviar mensaje
}
public boolean geldAbheben(double betrag) {
System.out.println(name + " will " + betrag + "€ abheben");
return konto.abheben(betrag); // Enviar mensaje
}
public void kontostandPruefen() {
double stand = konto.getKontostand(); // Enviar mensaje
System.out.println(name + "'s Kontostand: " + stand + "€");
}
}
// Uso de los mensajes
public class BankingDemo {
public static void main(String[] args) {
Bankkonto konto = new Bankkonto("DE123456789", 1000.0);
Kunde kunde = new Kunde("Max Mustermann", konto);
// Cadena de mensajes
kunde.geldEinzahlen(500.0);
kunde.kontostandPruefen();
if (kunde.geldAbheben(200.0)) {
System.out.println("Abhebung erfolgreich");
}
kunde.kontostandPruefen();
}
}
3. Implementación de Persistencia
// Serialización para persistencia de archivos
import java.io.*;
import java.util.*;
public class PersistenzDemo {
// Clase serializable
static class Produkt implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String name;
private double preis;
private transient Date lastModified; // transient = no se serializa
public Produkt(String id, String name, double preis) {
this.id = id;
this.name = name;
this.preis = preis;
this.lastModified = new Date();
}
// Getter y toString
public String getId() { return id; }
public String getName() { return name; }
public double getPreis() { return preis; }
@Override
public String toString() {
return String.format("Produkt[id=%s, name=%s, preis=%.2f]", id, name, preis);
}
}
// Administrador de persistencia
static class PersistenzManager {
private String dateiname;
public PersistenzManager(String dateiname) {
this.dateiname = dateiname;
}
// Guardar objetos
public void speichereProdukte(List<Produkt> produkte) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(dateiname))) {
oos.writeObject(produkte);
System.out.println("Produkte gespeichert in " + dateiname);
}
}
// Cargar objetos
@SuppressWarnings("unchecked")
public List<Produkt> ladeProdukte() throws IOException, ClassNotFoundException {
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(dateiname))) {
List<Produkt> produkte = (List<Produkt>) ois.readObject();
System.out.println("Produkte geladen aus " + dateiname);
return produkte;
}
}
}
// Persistencia JSON (manual)
static class JsonPersistenz {
public static void speichereAlsJson(List<Produkt> produkte, String dateiname) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(dateiname))) {
writer.write("[\n");
for (int i = 0; i < produkte.size(); i++) {
Produkt p = produkte.get(i);
writer.write(String.format(
" {\"id\": \"%s\", \"name\": \"%s\", \"preis\": %.2f}",
p.getId(), p.getName(), p.getPreis()
));
if (i < produkte.size() - 1) {
writer.write(",\n");
}
}
writer.write("\n]");
}
System.out.println("Produkte als JSON gespeichert");
}
}
public static void main(String[] args) {
List<Produkt> produkte = Arrays.asList(
new Produkt("P001", "Laptop", 999.99),
new Produkt("P002", "Maus", 29.99),
new Produkt("P003", "Tastatur", 79.99)
);
PersistenzManager manager = new PersistenzManager("produkte.ser");
try {
// Serialización
manager.speichereProdukte(produkte);
// Deserialización
List<Produkt> geladeneProdukte = manager.ladeProdukte();
geladeneProdukte.forEach(System.out::println);
// Persistencia JSON
JsonPersistenz.speichereAlsJson(produkte, "produkte.json");
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
4. Interfaces y APIs
// Interfaz de programación
interface DatenbankSchnittstelle {
// Métodos abstractos (sin implementación)
void verbinden() throws DatenbankException;
void trennen();
boolean istVerbunden();
// Métodos de consulta
List<Map<String, Object>> abfragen(String sql) throws DatenbankException;
int ausfuehren(String sql) throws DatenbankException;
// Métodos default (desde Java 8)
default void verbindenMitTimeout(int timeout) throws DatenbankException {
verbinden(); // Implementación estándar
}
}
// Clase de excepción personalizada
class DatenbankException extends Exception {
public DatenbankException(String nachricht) {
super(nachricht);
}
public DatenbankException(String nachricht, Throwable ursache) {
super(nachricht, ursache);
}
}
// Implementación concreta
class MySQLDatenbank implements DatenbankSchnittstelle {
private boolean verbunden = false;
private String verbindungsString;
public MySQLDatenbank(String verbindungsString) {
this.verbindungsString = verbindungsString;
}
@Override
public void verbinden() throws DatenbankException {
try {
// Conexión simulada
System.out.println("Verbinde zu MySQL: " + verbindungsString);
Thread.sleep(1000); // Simula retraso de red
verbunden = true;
System.out.println("Verbindung hergestellt");
} catch (InterruptedException e) {
throw new DatenbankException("Verbindung unterbrochen", e);
}
}
@Override
public void trennen() {
if (verbunden) {
System.out.println("Verbindung getrennt");
verbunden = false;
}
}
@Override
public boolean istVerbunden() {
return verbunden;
}
@Override
public List<Map<String, Object>> abfragen(String sql) throws DatenbankException {
if (!verbunden) {
throw new DatenbankException("Nicht verbunden");
}
System.out.println("Führe aus: " + sql);
// Resultado simulado
List<Map<String, Object>> ergebnis = new ArrayList<>();
Map<String, Object> zeile = new HashMap<>();
zeile.put("id", 1);
zeile.put("name", "Testdaten");
ergebnis.add(zeile);
return ergebnis;
}
@Override
public int ausfuehren(String sql) throws DatenbankException {
if (!verbunden) {
throw new DatenbankException("Nicht verbunden");
}
System.out.println("Führe aus: " + sql);
return 1; // Filas afectadas simuladas
}
}
// Uso de la API
public class ApiDemo {
public static void main(String[] args) {
// Uso polimórfico a través de la interfaz
DatenbankSchnittstelle db = new MySQLDatenbank("jdbc:mysql://localhost/test");
try {
// Trabajar a través de la interfaz
db.verbinden();
if (db.istVerbunden()) {
List<Map<String, Object>> ergebnis = db.abfragen("SELECT * FROM kunden");
System.out.println("Ergebnis: " + ergebnis.size() + " Zeilen");
int rows = db.ausfuehren("UPDATE kunden SET status = 'active'");
System.out.println("Betroffene Zeilen: " + rows);
}
} catch (DatenbankException e) {
System.err.println("Datenbankfehler: " + e.getMessage());
} finally {
db.trennen();
}
}
}
5. Ejemplo de Web-API
// REST API Controller (Ejemplo con Spring Boot)
@RestController
@RequestMapping("/api/kunden")
public class KundenAPI {
private final KundenService service;
public KundenAPI(KundenService service) {
this.service = service;
}
// GET /api/kunden/{id}
@GetMapping("/{id}")
public ResponseEntity<Kunde> getKunde(@PathVariable Long id) {
try {
Kunde kunde = service.findeKundeById(id);
return ResponseEntity.ok(kunde);
} catch (KundeNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
// POST /api/kunden
@PostMapping
public ResponseEntity<Kunde> createKunde(@RequestBody Kunde kunde) {
Kunde erstellterKunde = service.erstelleKunde(kunde);
return ResponseEntity.status(HttpStatus.CREATED).body(erstellterKunde);
}
// PUT /api/kunden/{id}
@PutMapping("/{id}")
public ResponseEntity<Kunde> updateKunde(@PathVariable Long id, @RequestBody Kunde kunde) {
try {
Kunde aktualisierterKunde = service.aktualisiereKunde(id, kunde);
return ResponseEntity.ok(aktualisierterKunde);
} catch (KundeNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
// DELETE /api/kunden/{id}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteKunde(@PathVariable Long id) {
service.loescheKunde(id);
return ResponseEntity.noContent().build();
}
}
// Modelo de datos
class Kunde {
private Long id;
private String name;
private String email;
private LocalDate geburtsdatum;
// Getters y Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public LocalDate getGeburtsdatum() { return geburtsdatum; }
public void setGeburtsdatum(LocalDate geburtsdatum) { this.geburtsdatum = geburtsdatum; }
}
Lecturas recomendadas: Programación Orientada a Objetos
Keine Bücher für Kategorie "objektorientierte-programmierung" gefunden.
Conceptos de POO en resumen
Encapsulación
// Los datos y métodos se agrupan en una unidad
public class Bankkonto {
private double kontostand; // Datos privados
public void einzahlen(double betrag) { // Método público
if (betrag > 0) {
kontostand += betrag;
}
}
public double getKontostand() {
return kontostand;
}
}
Abstracción
// La realidad compleja se simplifica
abstract class Fahrzeug {
protected String marke;
public abstract void beschleunigen();
public abstract void bremsen();
public void anzeigen() {
System.out.println("Fahrzeug: " + marke);
}
}
Polimorfismo
// Una interfaz, múltiples implementaciones
interface Tier {
void macheLaut();
}
class Hund implements Tier {
public void macheLaut() {
System.out.println("Wuff!");
}
}
class Katze implements Tier {
public void macheLaut() {
System.out.println("Miau!");
}
}
// Uso
Tier tier1 = new Hund();
Tier tier2 = new Katze();
tier1.macheLaut(); // Wuff!
tier2.macheLaut(); // Miau!
Estrategias de persistencia
Serialización
- Java Serialization: Interfaz
Serializable - JSON: Legible para humanos, independiente de plataforma
- XML: Estructurado, con metadatos
- Binary: Compacto, rápido
Persistencia en base de datos
- BD Relacional: Datos estructurados con SQL
- BD NoSQL: Documentos flexibles o clave-valor
- ORM: Object-Relational Mapping
- JPA/Hibernate: Java Persistence API
Persistencia en la nube
- Object Storage: S3, Azure Blob Storage
- Databases-as-a-Service: Firebase, Supabase
- Caché: Redis, Memcached
Tipos de API
Interfaces de programación
- APIs locales: Métodos dentro del mismo programa
- APIs de biblioteca: Bibliotecas externas
- APIs de framework: Spring, Django, React
APIs web
- REST: Métodos HTTP, códigos de estado
- GraphQL: Lenguaje de consulta flexible
- gRPC: RPC de alto rendimiento
- WebSocket: Comunicación en tiempo real
APIs de plataforma
- APIs del SO: Windows, Linux, macOS
- APIs móviles: Android, iOS
- APIs de nube: AWS, Azure, GCP
Ventajas y desventajas
Ventajas de los conceptos POO
- Estructuración: Organización clara del código
- Reutilización: Los componentes se pueden reutilizar
- Mantenibilidad: El diseño modular facilita los cambios
- Testabilidad: Los componentes aislados son fáciles de probar
- Escalabilidad: Los sistemas pueden crecer
Desventajas
- Complejidad: Overhead en proyectos pequeños
- Curva de aprendizaje: Muchos conceptos que entender
- Rendimiento: A veces más lento que código procedural
- Sobreingeniería: Riesgo de excesiva complejidad
Preguntas frecuentes de examen
-
¿Cuál es la diferencia entre atributo y método? Los atributos son propiedades/datos, los métodos son comportamiento/funciones de un objeto.
-
Explique el término mensaje en POO. El mensaje es la comunicación entre objetos, normalmente implementada como llamada a método.
-
¿Qué significa persistencia en programación? Almacenar datos de forma permanente para que estén disponibles más allá de las ejecuciones del programa.
-
¿Para qué sirven las interfaces? Definen contratos entre componentes y permiten acoplamiento débil y polimorfismo.
Fuentes principales
- https://de.wikipedia.org/wiki/Objektorientierte_Programmierung
- https://docs.oracle.com/javase/tutorial/java/concepts/
- https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/
Continúa en la ruta de aprendizaje de POO
El siguiente artículo en la ruta de aprendizaje de POO trata sobre OOP Encapsulación: Fundamentos, Information Hiding & Visibilidad, cómo la encapsulación oculta los estados internos.



