Contenido del curso
Contenido del curso
Luis Sandoval
Víctor Eusebio Olvera Thomé
Juan David Forero
Alfonso Navarro
Saul Sebastian Melgarejo Ramirez
Gustavo Olmedo
JUAN SILVA
Matias Ezequiel Franco Mancuello
Misael Gomez
Cristopher Alexander Reyes Portillo
Miguel Teheran
Marco Martín Peñafort Raholin
Miguel Teheran
Brandon Díaz
JUAN SILVA
ROMMEL DUAREZ SAENZ
Jose Carlos Vega Moron
Yulibeth Paola Barrios Castro
Luz Adriana
Daniel Mauricio Becerra Rincon
Daniel Mauricio Becerra Rincon
Luis Raymundo Solís Peralta
Buenas, en la clase EmployeeFullTime es necesario inicializar la propiedad de ExtraHours en el constructor de ExployeeFullTime.
namespace Liskov { public class EmployeeFullTime : Employee { public int ExtraHours {get;set;} public EmployeeFullTime(string fullname, int hoursWorked, int extrahours) : base(fullname, hoursWorked) { ExtraHours = extrahours; } public override decimal CalculateSalary() { decimal hourValue = 50; return hourValue * (HoursWorked + ExtraHours); } } }
Exacto, tuve que volver a ver la implementación para ver porque me daba a mi 8500 y a él 8000
Es correcto, a él le falto implementar esa porción de código en el constructor de esa clase: esto para poder hacer la asignación de las horas extra para realizar el calculo adecuado. Gracias por el aporte, compañero.
Desde mi perspectiva esta curso vale oro.
Es correcto, yo tengo varios años de experiencia en desarrollo y hasta este curso me di cuenta de que siempre he implementado SOLID pero nunca sabía cuál era cual 😦
Solo como una opinión, me gustaría que el código se mostrara multilínea para que se evite el uso del scroll horizontal y los alumnos podamos ver en una sola pantalla toda la línea del código
para ver mejor el codigo puedes verlo en el repositorio de github
En el foreach del archivo de Program.cs, estaría bueno cambiar el nombre del "item" por "itemEmployee" para que el nombre sea más descriptivo
Chat GPT ¡Claro! El Principio de Sustitución de Liskov (Liskov Substitution Principle, LSP) es uno de los cinco principios SOLID y fue propuesto por Barbara Liskov en 1987. Este principio se centra en la relación entre una clase base (o supertipo) y sus clases derivadas (o subtipos). La idea fundamental es que los objetos de una clase derivada deben poder ser usados en lugar de objetos de la clase base sin afectar la corrección del programa.
En términos más simples, si tienes una clase base (supertipo) y una clase derivada (subtipo), deberías poder sustituir una instancia de la clase base con una instancia de la clase derivada sin que el programa deje de funcionar correctamente.
Aquí hay una explicación más detallada:
Relación de herencia:
Figura y una clase derivada llamada Círculo. Según el LSP, deberías poder utilizar un objeto de tipo Círculo en cualquier lugar donde se espera un objeto de tipo Figura, ya que Círculo es un subtipo de Figura.Comportamiento consistente:
No alterar la invariante del tipo:
Pre y Post condiciones:
En resumen, el Principio de Sustitución de Liskov busca garantizar que las clases derivadas extiendan o especialicen el comportamiento de la clase base sin romper la lógica del programa. Esto facilita la creación de sistemas más flexibles y extensibles, ya que las nuevas clases pueden ser introducidas y utilizadas sin afectar el código existente que trabaja con la clase base.
Solamente estoy siguiendo la ruta de backend con c# y .net y en los cursos anteriores no recuerdo haber visot sobre "la clase base" osea cuando crea el constructor de la clase que ereda y agregan esto:
<code> public EmployeeFullTime(string fullname, int hoursWorked, int extrahours) : base(fullname, hoursWorked) { }
no se si puedo verlo en algún otro curso? o alguien me puede ayudar explicandome?
Desafortunadamente no lo tenemos, estamos trabajando en mas cursos, base es una keyword que hace referencia a la clase padre muy util para este tema de los constructores
Por qué en la clase employee (o sus subclases) no tiene declarado sus atributos, es decir, no tiene
private string fulllname; private int hoursWorked;
Este procesos de crear esas propiedadaes privadas y exponerlas con otras publicas se conoce como encapsulamiento. Cuando usas una clases como modelo para pasar datos entre componentes esto deja de ser tan necesario entonces se coloca la propiedad como publica y se agrega el {get;set;} para simplificar.
También podemos pasar la propiedad HourValue a la clase Employee, agregarla al constructor de esa clase abstracta, y cada subclase pasarlo directo sin necesidad que esta subclase lo pida en su constructor.
public Employee(string fullname, int hoursWorked, int hourValue) { Fullname = fullname; HoursWorked = hoursWorked; HourValue = hourValue; }
public EmployeeFullTime(string fullname, int hoursWorked, int extraHours) : base(fullname, hoursWorked, 50) { this.ExtraHours = extraHours; }
Estarias quemando el dato de horas extras. Es una mala practica
seria código duro...
Tengo una duda: Si pasamos la propiedad ExtraHours a la clase FullTime que pasaría si viene otro tipo de empleador que necesite también ExtraHours, estaríamos violando el principio de Liskov y OpenClose debido que tendríamos que modificar la clase EmployeeFullTime o en el mejor de los casos crear otra clase.
Tengo la misma duda
Entiendo que la clase base debería contener únicamente las propiedades y comportamientos que sean comunes a todas las clases derivadas. Si una propiedad como ExtraHours no aplica para todos los tipos de empleados, por ejemplo para Contractor, no debería estar en la clase base Employee.
En ese caso no sería tanto un problema de Liskov, sino de modelado de la jerarquía. Estaríamos forzando a algunas clases derivadas a tener una propiedad que no tiene sentido para ellas.
Si en el futuro aparecen varios tipos de empleados que manejan horas extras, una opción sería extraer ese comportamiento a una interfaz, por ejemplo IExtraHours, e implementarla únicamente en las clases que realmente soporten horas extras.
De esta forma mantenemos la clase base con responsabilidades comunes y evitamos modificar continuamente las clases existentes cuando aparezcan nuevos tipos de empleados, alineándonos mejor con el principio Open/Closed.
Respecto a tu pregunta de que si estaríamos violando Liskov y Open/Closed porque tendríamos que modificar EmployeeFullTime. Considero que no necesariamente ya que crear una nueva clase no viola Open/Closed. De hecho, Open/Closed promueve extender el comportamiento mediante nuevas clases en lugar de modificar las existentes. Solo habría un problema si constantemente tuviéramos que modificar EmployeeFullTime para soportar nuevos escenarios que no le corresponden.
Este codigo es otro ejemplo aplicando interfaces
interface IBird
{
void Eat();
}
interface IFlyableBird : IBird
{
void Fly();
}
class Sparrow : IFlyableBird
{
public void Eat()
{
Console.WriteLine("The sparrow is eating.");
}
public void Fly()
{
Console.WriteLine("The sparrow is flying.");
}
}
class Penguin : IBird
{
public void Eat()
{
Console.WriteLine("The penguin is eating.");
}
}
class Program
{
static void Main()
{
IFlyableBird flyingBird = new Sparrow();
flyingBird.Fly(); // Funciona bien ✅
IBird bird = new Penguin();
bird.Eat(); // No se espera que vuele, solo come ✅
}
}
Este principio nunca me habia quedado del todo claro pero con esta aplicacion me funciono bastante bien y ahora entiendo la funcionalidad del principio