Módulo 1 de 4 — Vista Lógica
3.1 Diagramas de Clases El diagrama de clases es el artefacto estrella de la Vista Lógica . Representa la estructura estática de un sistema orientado a objetos: qué elementos existen, qué información contienen, qué operaciones ejecutan y cómo colaboran entre sí.
📦 ¿Qué objetos existen? Las clases y entidades fundamentales que modelan el dominio del sistema.
📋 ¿Qué datos contienen? Atributos, tipos de datos y niveles de visibilidad (- privado, + público, # protegido).
⚡ ¿Qué pueden hacer? Constructores, métodos de negocio, getters/setters y firmas de retorno.
🔗 ¿Cómo se relacionan? Herencia (extends), contratos (implements), asociación (◇) y composición (◆).
💡 El plano universal: El diagrama UML es exactamente el mismo sin importar el lenguaje. En cada sección verás cómo se traduce directamente a Java, Python, C# y C++ .
¿Qué es una clase? Una clase es una representación o plantilla de un tipo de objeto dentro del sistema. En el modelado orientado a objetos y en UML, describe tres elementos fundamentales:
Usuario ← 1. Identidad (¿Qué es?)
- nombre: String
- email: String
← 2. Estado (¿Qué información tiene?) + login(): boolean
+ logout(): void
← 3. Comportamiento (¿Qué puede hacer?) 🏷️ 1. Identidad (Nombre)El nombre de la clase permite identificar inequívocamente qué concepto del dominio representa en el sistema (ej. Usuario, Libro, Factura).
📊 2. Estado (Atributos)Los atributos representan la información y valores que posee cada instancia (ej. nombre, email, saldo).
⚡ 3. Comportamiento (Métodos)Los métodos u operaciones representan las acciones y funciones que la clase puede ejecutar (ej. login(), logout(), calcularTotal()).
✨ Fórmula fundamental: Clase = Identidad + Estado + Comportamiento
1. Descripción de la clase y los atributos Un rectángulo UML con 3 compartimentos : nombre arriba, atributos al medio, métodos abajo. - privado, + público, # protegido.
Libro
- titulo: String String titulo titulo titulo
- autor: String String autor autor autor
- paginas: int int paginas paginas paginas
- prestado: boolean boolean prestado prestado prestado
+ getTitulo(): String String getTitulo() getTitulo() getTitulo()
+ prestar(): void void prestar() prestar() prestar()
🔍 Clic para ampliar y hacer zoom
1 public class Libro {
2
3 private String titulo;
4 private String autor;
5 private int paginas;
6 private boolean prestado ;
7
8
9 }
1 class Libro:
2 def __init__(self ):
3 self ._titulo = ""
4 self ._autor = ""
5 self ._paginas = 0
6 self ._prestado = False
7
8
9
1 public class Libro {
2 private string titulo;
3 private string autor;
4 private int paginas;
5 private bool prestado ;
6
7
8 }
1 class Libro {
2 private :
3 std ::string titulo;
4 std ::string autor ;
5 int paginas;
6 bool prestado ;
7 };
Regla UML: - titulo: String = privado String titulo. Si ves + es público. El tipo va después de :.
2. Constructor — con parámetro y sin parámetro El constructor lleva el mismo nombre que la clase y no tiene tipo de retorno . Permite crear el objeto ya inicializado. Sobrecarga = dos constructores con distinta firma.
Libro
- titulo: String String titulo titulo titulo
- autor: String String autor autor autor
+ Libro() Libro() Libro() Libro()
+ Libro(titulo: String, autor: String) Libro(String titulo, String autor) Libro(titulo, autor) Libro(titulo, autor)
+ Libro(titulo: String, paginas: int) Libro(String titulo, int paginas) Libro(titulo, paginas) Libro(titulo, paginas)
🔍 Clic para ampliar y hacer zoom
1 public class Libro {
2 private String titulo;
3 private String autor;
4
5 public Libro () {
6 this .titulo = "Sin título" ;
7 this .autor = "Anónimo" ;
8 }
9 public Libro (String titulo, String autor) {
10 this .titulo = titulo;
11 this .autor = autor;
12 }
13 public Libro (String titulo, int paginas) {
14 this .titulo = titulo;
15 this .paginas = paginas;
16 }
17 }
18 Libro l1 = new Libro ();
19 Libro l2 = new Libro ("Cien años" , "García Márquez" );
1 class Libro:
2 def __init__(self , titulo="" , autor ="" , paginas =0 ):
3
4 self ._titulo = titulo
5 self ._autor = autor
6 self ._paginas = paginas
7
8
9 l1 = Libro()
10
11 l2 = Libro("Cien años" , "García Márquez" , 471 )
1 public class Libro {
2 private string titulo;
3 private string autor;
4
5 public Libro () {
6 titulo = "Sin título" ;
7 autor = "Anónimo" ;
8 }
9 public Libro (string titulo, string autor) {
10 this .titulo = titulo;
11 this .autor = autor;
12 }
13
14 public Libro (string titulo, int paginas) : this () {
15 this .titulo = titulo;
16 this .paginas = paginas;
17 }
18 }
1 class Libro {
2 private :
3 std ::string titulo;
4 std ::string autor ;
5 public :
6 Libro () : titulo ("Sin título" ), autor ("Anónimo" ) {}
7 Libro (std ::string t, std ::string a) : titulo (t), autor (a) {}
8 Libro (std ::string t, int p) : titulo (t), paginas (p) {}
9 private :
10 int paginas;
11 };
⭐ En UML el constructor se reconoce porque se llama igual que la clase y no muestra retorno. Si hay dos, es sobrecarga.
3. Setters and Getters — encapsulamiento Atributos private + métodos getTitulo()/setTitulo() para controlar acceso y validación. En el diagrama: + getTitulo(): String y + setTitulo(t:String): void. Excepción Java: si el atributo es boolean, el getter se llama isPrestado() no getPrestado() (JavaBeans).
Libro
- titulo: String String titulo titulo titulo
- paginas: int int paginas paginas paginas
- prestado: boolean boolean prestado prestado prestado
+ getTitulo(): String String getTitulo() getTitulo() getTitulo()
+ setTitulo(t: String): void void setTitulo(String t) setTitulo(t) setTitulo(t)
+ getPaginas(): int int getPaginas() getPaginas() getPaginas()
+ setPaginas(p: int): void void setPaginas(int p) setPaginas(p) setPaginas(p)
+ isPrestado(): boolean boolean isPrestado() isPrestado() isPrestado()
+ setPrestado(p: boolean): void void setPrestado(boolean p) setPrestado(p) setPrestado(p)
🔍 Clic para ampliar y hacer zoom
1 public class Libro {
2 private String titulo;
3 private int paginas;
4 private boolean prestado ;
5
6 public String getTitulo () {
7 return titulo;
8 }
9 public void setTitulo (String titulo) {
10 if (titulo == null || titulo.isBlank ()) throw new IllegalArgumentException ();
11 this .titulo = titulo;
12 }
13 public int getPaginas () { return paginas; }
14 public void setPaginas (int paginas) {
15 if (paginas < 0 ) throw new IllegalArgumentException ();
16 this .paginas = paginas;
17 }
18
19 public boolean isPrestado () {
20 return prestado ;
21 }
22 public void setPrestado (boolean prestado ) {
23 this .prestado = prestado ;
24 }
25 }
1 class Libro:
2 def __init__(self ):
3 self ._titulo = ""
4
5 @property
6 def titulo(self ):
7 return self ._titulo
8
9 @titulo .setter
10 def titulo(self , valor ):
11 if not valor :
12 raise ValueError ("título vacío" )
13 self ._titulo = valor
14
15 l = Libro()
16 l.titulo = "Rayuela"
17 print (l.titulo)
1 public class Libro {
2 private string titulo;
3
4 public string Titulo {
5 get => titulo;
6 set {
7 if (string .IsNullOrWhiteSpace (value)) throw new ArgumentException ();
8 titulo = value;
9 }
10 }
11
12 public int Paginas { get ; set ; }
13 }
1 class Libro {
2 private :
3 std ::string titulo;
4 int paginas;
5 bool prestado ;
6 public :
7 std ::string getTitulo () const { return titulo; }
8 void setTitulo (const std ::string & t) {
9 if (t.empty ()) throw std ::invalid_argument ("vacío" );
10 titulo = t;
11 }
12 int getPaginas () const { return paginas; }
13 void setPaginas (int p) { paginas = p; }
14 bool isPrestado () const { return prestado ; }
15 void setPrestado (bool p) { prestado = p; }
16 };
☕ Java tip — boolean: isPrestado() no getPrestado(). private boolean prestado; → isPrestado() / setPrestado(). Frameworks (Spring, Jackson) lo esperan así.
4. Métodos de clase personalizados Más allá de getters/setters, la clase expone comportamiento : prestar(), devolver(), estaDisponible().
Libro
- prestado: boolean boolean prestado prestado prestado
+ prestar(): void void prestar() prestar() prestar()
+ devolver(): void void devolver() devolver() devolver()
+ estaDisponible(): boolean boolean estaDisponible() estaDisponible() estaDisponible()
+ descripcion(): String String descripcion() descripcion() descripcion()
🔍 Clic para ampliar y hacer zoom
1 public class Libro {
2 private boolean prestado ;
3
4 public void prestar () {
5 if (prestado ) throw new IllegalStateException ("Ya prestado" );
6 prestado = true;
7 }
8 public void devolver () { prestado = false; }
9 public boolean estaDisponible () { return !prestado ; }
10 public String descripcion () { return "Libro prestado=" + prestado ; }
11 }
1 class Libro:
2 def __init__(self ):
3 self ._prestado = False
4
5 def prestar(self ):
6 if self ._prestado:
7 raise Exception("Ya prestado" )
8 self ._prestado = True
9
10 def devolver(self ):
11 self ._prestado = False
12
13 def esta_disponible(self ) -> bool :
14 return not self ._prestado
15
16 def descripcion(self ) -> str :
17 return f"Libro prestado={self._prestado}"
1 public class Libro {
2 private bool prestado ;
3 public void Prestar () {
4 if (prestado ) throw new InvalidOperationException ();
5 prestado = true;
6 }
7 public void Devolver () => prestado = false;
8 public bool EstaDisponible () => !prestado ;
9 public string Descripcion () => $"Libro prestado={prestado}" ;
10 }
1 class Libro {
2 private :
3 bool prestado = false ;
4 public :
5 void prestar () {
6 if (prestado ) throw std ::logic_error ("Ya prestado" );
7 prestado = true ;
8 }
9 void devolver () { prestado = false ; }
10 bool estaDisponible () const { return !prestado ; }
11 std ::string descripcion () const { return prestado ? "prestado" : "disponible" ; }
12 };
5. Override — reescribir el comportamiento Una subclase reescribe un método heredado para especializarlo. En UML se ve el mismo método en padre e hija; en código lleva anotación.
Publicacion
- titulo: String String titulo titulo titulo
+ mostrar(): String String mostrar() mostrar() mostrar()
Libro
- paginas: int int paginas paginas paginas
+ mostrar(): String String mostrar() mostrar() mostrar()
Revista
- numero: int int numero numero numero
+ mostrar(): String String mostrar() mostrar() mostrar()
EBook
- tamanoMb: double double tamanoMb tamanoMb tamanoMb
+ mostrar(): String String mostrar() mostrar() mostrar()
🔍 Clic para ampliar y hacer zoom
1 public class Publicacion {
2 protected String titulo;
3 public Publicacion (String titulo) { this .titulo = titulo; }
4 public String mostrar () { return "Publicación: " + titulo; }
5 }
6 public class Libro extends Publicacion {
7 private int paginas;
8 public Libro (String titulo, int paginas) {
9 super (titulo); this .paginas = paginas;
10 }
11 @Override
12 public String mostrar () {
13 return "Libro: " + titulo + " (" + paginas + " pág.)" ;
14 }
15 }
1 class Publicacion:
2 def __init__(self , titulo):
3 self .titulo = titulo
4 def mostrar(self ) -> str :
5 return f"Publicación: {self.titulo}"
6
7 class Libro(Publicacion):
8 def __init__(self , titulo, paginas ):
9 super ().__init__(titulo)
10 self .paginas = paginas
11 def mostrar(self ) -> str :
12 return f"Libro: {self.titulo} ({self.paginas} pág.)"
13
14 print (Libro("Rayuela" , 300 ).mostrar())
1 public class Publicacion {
2 protected string titulo;
3 public Publicacion (string titulo) => this .titulo = titulo;
4 public virtual string Mostrar () => $"Publicación: {titulo}" ;
5 }
6 public class Libro : Publicacion {
7 private int paginas;
8 public Libro (string t, int p) : base (t) => paginas = p;
9 public override string Mostrar () => $"Libro: {titulo} ({paginas} pág.)" ;
10 }
1 class Publicacion {
2 protected :
3 std ::string titulo;
4 public :
5 Publicacion (std ::string t) : titulo (t) {}
6 virtual std ::string mostrar () const {
7 return "Publicación: " + titulo;
8 }
9 virtual ~Publicacion () = default ;
10 };
11 class Libro : public Publicacion {
12 int paginas;
13 public :
14 Libro (std ::string t, int p) : Publicacion (t), paginas (p) {}
15 std ::string mostrar () const override {
16 return "Libro: " + titulo + " (" + std ::to_string (paginas) + " pág.)" ;
17 }
18 };
⭐ super() / super.mostrar() llama al padre. @Override en Java y override en C++/C# evitan errores si cambias la firma.
6. Conexiones — asociación y composición Las clases rara vez viven solas. Una clase usa otra como atributo:
Asociación (◇—): una clase tiene otra pero no la posee. Libro tiene Etiqueta → si borro el libro, las etiquetas pueden seguir vivas.Composición (◆—): una clase posee completamente a otra. Libro compone Autor → si borro el libro, su referencia al autor se destruye también.En UML: diamante vacío (◇) = asociación débil, diamante lleno (◆) = composición fuerte.
Libro
- titulo: String String titulo titulo titulo
+ getAutor(): Autor Autor getAutor() getAutor() getAutor()
+ addEtiqueta(e: Etiqueta): void void addEtiqueta(Etiqueta e) addEtiqueta(e) addEtiqueta(e)
◆ Composición (◆)
Autor
- nombre: String String nombre nombre nombre
◇ Asociación (◇)
Etiqueta
- nombre: String String nombre nombre nombre
🔍 Clic para ampliar y hacer zoom
1 import java.util.ArrayList ;
2 import java.util.List ;
3
4 public class Libro {
5 private String titulo;
6 private Autor autor;
7 private List <Etiqueta> etiquetas;
8
9 public Libro (String titulo, Autor autor) {
10 this .titulo = titulo;
11 this .autor = autor;
12 this .etiquetas = new ArrayList <>();
13 }
14 public Autor getAutor () { return autor; }
15 public void addEtiqueta (Etiqueta e) { etiquetas.add (e); }
16 }
17 Libro l = new Libro ("Rayuela" , new Autor ("Cortázar" ));
18 l.addEtiqueta (new Etiqueta ("novela" ))
1 class Autor :
2 def __init__(self , nombre):
3 self .nombre = nombre
4
5 class Etiqueta:
6 def __init__(self , nombre):
7 self .nombre = nombre
8
9 class Libro:
10 def __init__(self , titulo, autor ):
11 self .titulo = titulo
12 self .autor = autor
13 self .etiquetas = []
14
15 def add_etiqueta(self , etiqueta):
16 self .etiquetas .append(etiqueta)
17
18 a = Autor ("García Márquez" )
19 l = Libro("Cien años" , a)
20 l.add_etiqueta(Etiqueta("realismo" ))
1 public class Libro {
2 private string titulo;
3 private Autor autor;
4 private List <Etiqueta> etiquetas;
5
6 public Libro (string titulo, Autor autor) {
7 this .titulo = titulo;
8 this .autor = autor;
9 this .etiquetas = new List <Etiqueta>();
10 }
11 public Autor Autor => autor;
12 public void AddEtiqueta (Etiqueta e) => etiquetas.Add (e);
13 }
14 var l = new Libro ("Rayuela" , new Autor ("Cortázar" ));
15 l.AddEtiqueta (new Etiqueta ("novela" ))
1 #include <vector>
2 #include <string>
3
4 class Autor {
5 public :
6 std ::string nombre;
7 Autor (std ::string n) : nombre (n) {}
8 };
9
10 class Etiqueta {
11 public :
12 std ::string nombre;
13 Etiqueta (std ::string n) : nombre (n) {}
14 };
15
16 class Libro {
17 std ::string titulo;
18 Autor autor ;
19 std ::vector <Etiqueta> etiquetas;
20 public :
21 Libro (std ::string t, Autor a) : titulo (t), autor (a) {}
22 Autor getAutor () const { return autor ; }
23 void addEtiqueta (Etiqueta e) { etiquetas.push_back (e); }
24 };
⭐ En UML la línea con diamante va del contenedor al contenido. Diamante vacío (◇) = asociación (etiquetas sobreviven). Diamante lleno (◆) = composición (el contenido muere con el contenedor). El número junto a la línea indica cardinalidad : 1, 0..*, 1..*.
7. Herencia — class Libro extends Publicacion La herencia permite reutilizar código : la subclase hereda atributos y métodos del padre y puede añadir los suyos o reescribirlos.
En UML: triángulo vacío (▽) apunta del hijo al padre. Relación"es-un" : Libro es una Publicacion.
Publicacion
- titulo: String String titulo titulo titulo
- isbn: String String isbn isbn isbn
+ getTitulo(): String String getTitulo() getTitulo() getTitulo()
+ descripcion(): String String descripcion() descripcion() descripcion()
Libro
- paginas: int int paginas paginas paginas
+ getPaginas(): int int getPaginas() getPaginas() getPaginas()
+ descripcion(): String String descripcion() descripcion() descripcion()
Revista
- numero: int int numero numero numero
- frecuencia: String String frecuencia frecuencia frecuencia
+ getNumero(): int int getNumero() getNumero() getNumero()
+ descripcion(): String String descripcion() descripcion() descripcion()
EBook
- tamanoMb: double double tamanoMb tamanoMb tamanoMb
+ getTamanoMb(): double double getTamanoMb() getTamanoMb() getTamanoMb()
+ descripcion(): String String descripcion() descripcion() descripcion()
🔍 Clic para ampliar y hacer zoom
1 public class Publicacion {
2 protected String titulo;
3 protected String isbn;
4 public Publicacion (String titulo, String isbn) {
5 this .titulo = titulo;
6 this .isbn = isbn;
7 }
8 public String getTitulo () { return titulo; }
9 public String descripcion () { return "Publicación: " + titulo; }
10 }
11
12 public class Libro extends Publicacion {
13 private int paginas;
14 public Libro (String titulo, String isbn, int paginas) {
15 super (titulo, isbn);
16 this .paginas = paginas;
17 }
18 public int getPaginas () { return paginas; }
19 @Override
20 public String descripcion () {
21 return "Libro: " + titulo + " (" + paginas + " pág.)" ;
22 }
23 }
24
25 public class Revista extends Publicacion {
26 private int numero;
27 private String frecuencia;
28 public Revista (String titulo, String isbn, int numero, String frecuencia) {
29 super (titulo, isbn);
30 this .numero = numero;
31 this .frecuencia = frecuencia;
32 }
33 public int getNumero () { return numero; }
34 @Override
35 public String descripcion () {
36 return "Revista #" + numero + " (" + frecuencia + ")" ;
37 }
38 }
1 class Publicacion:
2 def __init__(self , titulo, isbn):
3 self .titulo = titulo
4 self .isbn = isbn
5 def descripcion(self ):
6 return f"Publicación: {self.titulo}"
7
8 class Libro(Publicacion):
9 def __init__(self , titulo, isbn, paginas ):
10 super ().__init__(titulo, isbn)
11 self .paginas = paginas
12 def descripcion(self ):
13 return f"Libro: {self.titulo} ({self.paginas} pág.)"
14
15 class Revista(Publicacion):
16 def __init__(self , titulo, isbn, numero, frecuencia):
17 super ().__init__(titulo, isbn)
18 self .numero = numero
19 self .frecuencia = frecuencia
20 def descripcion(self ):
21 return f"Revista #{self.numero} ({self.frecuencia})"
22
23 class EBook(Publicacion):
24 def __init__(self , titulo, isbn, tamano_mb):
25 super ().__init__(titulo, isbn)
26 self .tamano_mb = tamano_mb
27 def descripcion(self ):
28 return f"EBook: {self.titulo} ({self.tamano_mb} MB)"
1 public class Publicacion {
2 protected string titulo;
3 protected string isbn;
4 public Publicacion (string titulo, string isbn) {
5 this .titulo = titulo;
6 this .isbn = isbn;
7 }
8 public string Titulo => titulo;
9 public virtual string Descripcion () => $"Publicación: {titulo}" ;
10 }
11
12 public class Libro : Publicacion {
13 private int paginas;
14 public Libro (string t, string isbn, int p) : base (t, isbn) => paginas = p;
15 public int Paginas => paginas;
16 public override string Descripcion () => $"Libro: {titulo} ({paginas} pág.)" ;
17 }
18
19 public class Revista : Publicacion {
20 private int numero;
21 private string frecuencia;
22 public Revista (string t, string isbn, int n, string f) : base (t, isbn) {
23 numero = n;
24 frecuencia = f;
25 }
26 public override string Descripcion () => $"Revista #{numero} ({frecuencia})" ;
27 }
1 class Publicacion {
2 protected :
3 std ::string titulo;
4 std ::string isbn;
5 public :
6 Publicacion (std ::string t, std ::string i) : titulo (t), isbn (i) {}
7 std ::string getTitulo () const { return titulo; }
8 virtual std ::string descripcion () const {
9 return "Publicación: " + titulo;
10 }
11 virtual ~Publicacion () = default ;
12 };
13
14 class Libro : public Publicacion {
15 int paginas;
16 public :
17 Libro (std ::string t, std ::string i, int p)
18 : Publicacion (t, i), paginas (p) {}
19 int getPaginas () const { return paginas; }
20 std ::string descripcion () const override {
21 return "Libro: " + titulo + " (" + std ::to_string (paginas) + " pág.)" ;
22 }
23 };
24
25 class Revista : public Publicacion {
26 int numero;
27 std ::string frecuencia;
28 public :
29 Revista (std ::string t, std ::string i, int n, std ::string f)
30 : Publicacion (t, i), numero (n), frecuencia (f) {}
31 std ::string descripcion () const override {
32 return "Revista #" + std ::to_string (numero) + " (" + frecuencia + ")" ;
33 }
34 };
Herencia vs Composición: Usa herencia cuando la relación es "es-un" (Libro es Publicación). Usa composición cuando es "tiene-un" (Libro tiene Autor). Preferir composición sobre herencia cuando sea posible.
8. Interfaces — implements Imprimible Una interfaz es un contrato : define qué métodos debe tener una clase pero no cómo se implementan. Una clase puede implementar múltiples interfaces (a diferencia de heredar de un solo padre).
En UML: se escribe <<interface>> en la cabecera y la flecha es línea punteada con triángulo (▽LineStyle::dashed).
<<interface>> Imprimible
+ imprimir(): String String imprimir() imprimir() imprimir()
Libro
- titulo: String String titulo titulo titulo
+ imprimir(): String String imprimir() imprimir() imprimir()
Revista
- numero: int int numero numero numero
+ imprimir(): String String imprimir() imprimir() imprimir()
Recibo
- monto: double double monto monto monto
+ imprimir(): String String imprimir() imprimir() imprimir()
🔍 Clic para ampliar y hacer zoom
1 public interface Imprimible {
2 String imprimir ();
3 }
4
5 public class Libro implements Imprimible {
6 private String titulo;
7 public Libro (String titulo) { this .titulo = titulo; }
8 @Override
9 public String imprimir () { return "Libro: " + titulo; }
10 }
11
12 public class Revista implements Imprimible {
13 private int numero;
14 public Revista (int numero) { this .numero = numero; }
15 @Override
16 public String imprimir () { return "Revista #" + numero; }
17 }
18
19 public class Recibo implements Imprimible {
20 private double monto;
21 public Recibo (double monto) { this .monto = monto; }
22 @Override
23 public String imprimir () { return "Recibo: $" + monto; }
24 }
25
26
27 Imprimible[] docs = { new Libro ("Rayuela" ), new Revista (42 ), new Recibo (2500 ) };
28 for (Imprimible d : docs) {
29 System.out.println (d.imprimir ());
30 }
1 from abc import ABC, abstractmethod
2
3 class Imprimible(ABC):
4 @abstractmethod
5 def imprimir(self ) -> str :
6 pass
7
8 class Libro(Imprimible):
9 def __init__(self , titulo):
10 self .titulo = titulo
11 def imprimir(self ) -> str :
12 return f"Libro: {self.titulo}"
13
14 class Revista(Imprimible):
15 def __init__(self , numero):
16 self .numero = numero
17 def imprimir(self ) -> str :
18 return f"Revista #{self.numero}"
19
20 class Recibo(Imprimible):
21 def __init__(self , monto):
22 self .monto = monto
23 def imprimir(self ) -> str :
24 return "Recibo: $" + str (self .monto)
25
26
27 docs = [Libro("Rayuela" ), Revista(42 ), Recibo(2500 )]
28 for d in docs:
29 print (d.imprimir())
1 public interface Imprimible {
2 string Imprimir ();
3 }
4
5 public class Libro : Imprimible {
6 private string titulo;
7 public Libro (string titulo) => this .titulo = titulo;
8 public string Imprimir () => $"Libro: {titulo}" ;
9 }
10
11 public class Revista : Imprimible {
12 private int numero;
13 public Revista (int numero) => this .numero = numero;
14 public string Imprimir () => $"Revista #{numero}" ;
15 }
16
17 public class Recibo : Imprimible {
18 private double monto;
19 public Recibo (double monto) => this .monto = monto;
20 public string Imprimir () => "Recibo: $" + monto;
21 }
22
23
24 Imprimible[] docs = { new Libro ("Rayuela" ), new Revista (42 ), new Recibo (2500 ) };
25 foreach (var d in docs) Console .WriteLine (d.Imprimir ());
1 class Imprimible {
2 public :
3 virtual std ::string imprimir () const = 0 ;
4 virtual ~Imprimible () = default ;
5 };
6
7 class Libro : public Imprimible {
8 std ::string titulo;
9 public :
10 Libro (std ::string t) : titulo (t) {}
11 std ::string imprimir () const override {
12 return "Libro: " + titulo;
13 }
14 };
15
16 class Revista : public Imprimible {
17 int numero;
18 public :
19 Revista (int n) : numero (n) {}
20 std ::string imprimir () const override {
21 return "Revista #" + std ::to_string (numero);
22 }
23 };
24
25 class Recibo : public Imprimible {
26 double monto;
27 public :
28 Recibo (double m) : monto (m) {}
29 std ::string imprimir () const override {
30 return "Recibo: $" + std ::to_string (monto);
31 }
32 };
33
34
35 #include <vector>
36 #include <memory>
37 std ::vector <std ::unique_ptr <Imprimible>> docs;
38 docs.push_back (std ::make_unique<Libro>("Rayuela" ));
39 docs.push_back (std ::make_unique<Revista>(42 ));
40 docs.push_back (std ::make_unique<Recibo>(2500 ));
41 for (const auto & d : docs) {
42 std ::cout << d->imprimir () << std ::endl ;
43 }
Herencia vs Interface: Herencia = "es-un" (un tipo). Interface = "puede-hacer" (un comportamiento). Java/C# permiten heredar de un solo padre pero implementarmúltiples interfaces . Ej: class Libro extends Publicacion implements Imprimible, Serializable.
Resumen — Los 4 pilares de las Clases 1. Clase Atributos + métodos + constructores + getters/setters
2. Conexiones Asociación (◇) y Composición (◆)
3. Herencia extends — relación "es-un"
4. Interfaces implements — contrato "puede-hacer"
Practica con los desafíos: Herencia e Interfaces .
🧱 Reto: Modela tu Libro completo Crea una clase Libro con atributos titulo, autor, paginas, prestado, dos constructores (vacío y con titulo/autor), getters/setters con validación, métodos prestar()/devolver() y una subclase LibroDigital que haga override de mostrar().
👁️ Ver esquema UML esperado Libro
- titulo: String String titulo titulo titulo
- autor: String String autor autor autor
- paginas: int int paginas paginas paginas
- prestado: boolean boolean prestado prestado prestado
+ Libro() Libro() Libro() Libro()
+ Libro(titulo: String, autor: String) Libro(String titulo, String autor) Libro(titulo, autor) Libro(titulo, autor)
+ getTitulo(): String String getTitulo() getTitulo() getTitulo()
+ setTitulo(t: String): void void setTitulo(String t) setTitulo(t) setTitulo(t)
+ prestar(): void void prestar() prestar() prestar()
+ devolver(): void void devolver() devolver() devolver()
+ mostrar(): String String mostrar() mostrar() mostrar()
LibroDigital
- tamanoMb: double double tamanoMb tamanoMb tamanoMb
+ mostrar(): String String mostrar() mostrar() mostrar()
LibroFisico
- estante: String String estante estante estante
+ mostrar(): String String mostrar() mostrar() mostrar()
Audiolibro
- duracionMin: int int duracionMin duracionMin duracionMin
+ mostrar(): String String mostrar() mostrar() mostrar()
🔍 Clic para ampliar y hacer zoom
Implementa en el lenguaje del selector y compara.
Ponte a prueba
🏛️ Comenzar Arquitectura Quiz
Son 10 preguntas de opción múltiple sobre esta lección. ¡Evalúa tus conocimientos!
← Vista Lógica Vista de Desarrollo →