No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Aplicando el principio abierto/cerrado

8/16
Recursos

Aportes 19

Preguntas 5

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

La respuesta del reto implementando la “interface”

Interface Employee

namespace OpenClose
{  
	public interface IEmployee
  	{
    		public string Fullname { get; set; }
		public int HoursWorked { get; set; }
    		public decimal CalculateSalaryMonthly();
  	}
}

Y en las clases

Método EmployeePartTime

public class EmployeePartTime : IEmployee
    {
        public string Fullname { get ; set ; }
        public int HoursWorked { get ; set ; }

        public EmployeePartTime(string fullname, int hoursWorked)
        {
            Fullname = fullname;
            HoursWorked = hoursWorked;
        }

        public decimal CalculateSalaryMonthly()
        {
            decimal hourValue = 20000M;
                
            decimal salary = hourValue * HoursWorked;
            if (HoursWorked > 160) {
                decimal effortCompensation = 5000M;
                int extraDays = HoursWorked - 160;
                salary += effortCompensation * extraDays;
            }
            return salary;
        }
    } 

Método EmployeeFullTime

public class EmployeeFullTime : IEmployee
    {
        public string Fullname { get ; set ; }
        public int HoursWorked { get ; set; }

        public EmployeeFullTime(string fullname, int hoursWorked)
        {
            Fullname = fullname;
            HoursWorked = hoursWorked;
        }

        public decimal CalculateSalaryMonthly()
        {
            decimal hourValue = 30000M;
            decimal salary = hourValue * HoursWorked;
            return salary;
        }
    }

y program

using OpenClose;

CalculateSalaryMonthly(new List<IEmployee>() {
    new EmployeeFullTime("Pepito Pérez", 160),
    new EmployeePartTime("Manuel Lopera", 180)
});


void CalculateSalaryMonthly(List<IEmployee> employees) 
{
    foreach (var employee in employees)
    {
        Console.WriteLine($"Empleado: {employee.Fullname}, Pago: {employee.CalculateSalaryMonthly()} ");
    }
}

El concepto de clase Abstracta siempre me ha costado trabajo. Este ejercicio, deja más claro de qué se trata

En el CalculateSalaryMonthly() de la clase EmployeePartTime hace falta las lineas de código para calcular las horas extras cuando es mayor a 160

if (HoursWorked > 160) {
                decimal effortCompensation = 5000M;
                int extraDays = HoursWorked - 160;
                salary += effortCompensation * extraDays;
            }

asi quisiera ganar yo al mes😢… $4,800,000.0

Yo cambie la clase abstracta porque el salario considero debe ir dentro

namespace OpenClose; 

public abstract class Employee 
{
    public string Fullname { get; }
    public int HoursWorked { get; }
    public decimal HourValue { get; }

    public Employee(string fullname, int hoursWorked, decimal hourValue)
    {
        Fullname = fullname; 
        HoursWorked = hoursWorked; 
        HourValue = hourValue; 
    }
    
    public abstract decimal CalculateMonthlySalary(); 
}
public class EmployeeFullTime : Employee
    {

        public EmployeeFullTime(string fullname, int hoursWorked, decimal hourValue)
        : base(fullname, hoursWorked, hourValue)
        {
        }

        public override decimal CalculateMonthlySalary()
        {
            return HourValue * HoursWorked;
        }
    }
public class EmployeePartTime : Employee
    {
        public int hoursLimitForExtraCompensation { get; set; } = 160; 
        public decimal effortCompensation  { get; set; } = 5000M; 

        public EmployeePartTime(string fullname, int hoursWorked, decimal hourValue)
        : base(fullname, hoursWorked, hourValue)
        {
        }

        public override decimal CalculateMonthlySalary()
        {
            var salary = HourValue * HoursWorked;
            if (HoursWorked > hoursLimitForExtraCompensation) {
                int extraDays = HoursWorked - hoursLimitForExtraCompensation;
                salary += effortCompensation * extraDays;
            }
            return salary;
        }
    }

Gracias, ahora si pude comprender lo de las Clases Abstractas, les dejo una pagina muy interesante

https://dotnettutorials.net/lesson/open-closed-principle/

Me pareció super interesante la implementación de clases abstractas e interfaces. Cabe aclarar que las interfaces se implementan muy similar entre lenguajes de programación. Para C#, la inteligencia artificial de notion me deja el siguiente ejemplo:
Las clases abstractas y las interfaces son herramientas utilizadas en la programación orientada a objetos para facilitar la creación de componentes con comportamientos comunes.

Clases abstractas:

  • Una clase abstracta es una clase que no se puede instanciar, pero que se puede utilizar como plantilla para crear otras clases.
  • Las clases abstractas pueden contener métodos abstractos, que son métodos sin implementación. Estos métodos deben ser implementados en las clases que heredan de la clase abstracta.
  • Las clases abstractas pueden contener métodos con implementación, que las clases que heredan pueden usar directamente o sobrescribir si es necesario.

Un ejemplo de una clase abstracta en C#:

public abstract class Animal
{
    public abstract void MakeSound();

    public void Sleep()
    {
        Console.WriteLine("Zzzzz");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}

public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Meow!");
    }
}

En este ejemplo, Animal es una clase abstracta que contiene un método abstracto MakeSound() y un método con implementación Sleep(). La clase Dog y la clase Cat heredan de Animal y proporcionan su propia implementación del método MakeSound().

Interfaces:

  • Una interfaz es una especificación de un conjunto de métodos que una clase debe implementar.
  • Las interfaces no tienen implementación, solo especifican la firma de los métodos que deben ser implementados por las clases que las implementan.
  • Las clases pueden implementar múltiples interfaces.

Un ejemplo de una interfaz en C#:

public interface IShape
{
    double Area();
    double Perimeter();
}

public class Rectangle : IShape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public double Area()
    {
        return Width * Height;
    }

    public double Perimeter()
    {
        return 2 * (Width + Height);
    }
}

public class Circle : IShape
{
    public double Radius { get; set; }

    public double Area()
    {
        return Math.PI * Radius * Radius;
    }

    public double Perimeter()
    {
        return 2 * Math.PI * Radius;
    }
}

En este ejemplo, IShape es una interfaz que especifica dos métodos Area() y Perimeter(). La clase Rectangle y la clase Circle implementan IShape y proporcionan su propia implementación de los métodos Area() y Perimeter().

Cabe aclarar que, para resolver el reto por medio de interfaces, es necesario implementar todo lo que posee un interfaz, ya sean métodos o propiedades. Dejo un ejemplo de la implementación del EmpleadoTiempoCompleto:

 namespace OpenClose
{
    public class EmployeeFullTime : IEmployee
    {
        public string Fullname { get ; set ; }
        public int HoursWorked { get ; set ; }
        public EmployeeFullTime(string fullname, int hoursWorked)
        {
            Fullname = fullname;
            HoursWorked = hoursWorked;
        }

        

        public decimal CalculateSalaryMonthly()
        {
            decimal hourValue = 30000M;
            decimal salary = hourValue * HoursWorked;
            return salary;
        }
    }
}

Personalmente, recomendaría utilizar interfaces en lugar de clases abstractas en proyectos de C#. Las interfaces ofrecen flexibilidad y versatilidad en el diseño de tu aplicación, ya que una clase puede implementar múltiples interfaces. Esto te permite componer y reutilizar código de manera más efectiva.

Además, el uso de interfaces promueve la separación de preocupaciones y un diseño más modular, lo cual facilita el mantenimiento y la prueba de tu código.

Las interfaces son especialmente útiles en escenarios donde la herencia múltiple de clases no está permitida en C#. Al implementar interfaces, puedes definir contratos claros y comportamientos esperados sin estar limitado a una única clase base.

Además, el uso de interfaces reduce el acoplamiento entre componentes y te brinda un diseño más flexible y mantenible. Al depender de contratos en lugar de implementaciones concretas, puedes realizar cambios futuros sin afectar otras partes del sistema.

La respuesta al reto:

interface IEmployee
    {
        decimal CalculateSalaryMonthly();
        string Fullname { get; set; }
    }
    public abstract class Employee: IEmployee
    {
        public string Fullname { get; set; } = "";
        public int HoursWorked { get; set; }
        public abstract decimal CalculateSalaryMonthly();
    }

Entonces la subclase queda asi:

 public class EmployeeContractor: Employee
    {
        public EmployeeContractor(string fullname, int hoursWorked)
        {
            Fullname = fullname;
            HoursWorked = hoursWorked;
        }  
        public override decimal CalculateSalaryMonthly()
        {
            decimal hourValue = 34000M;
            decimal salary = hourValue * HoursWorked;

            return salary;
        }
    }

Y el programa:

ShowSalaryMonthly(new List<IEmployee>() {
    new EmployeeFullTime("Pepito Pérez", 160),
    new EmployeeContractor("Mariana Gómez", 140),
    new EmployeePartTime("Manuel Lopera", 180)
});

Excelente explicación
Excelente explicación
Mi aporte para el reto utilizando ambos temas a la clase (Abstract e Interface) **Class IEmployee** ```c# namespace OpenClose.Interface { public interface IEmployee { public string Fullname { get; set; } public int HoursWorked { get; set; } public decimal CalculateSalaryMonthlyInterface(); } } ``` **Class EmployeeContrator.cs** ```c# #region Using an abstract class and an interface using OpenClose.Interface; namespace OpenClose { public class EmployeeContractor : Employee, IEmployee { public EmployeeContractor(string fullname, int hoursWorked) { Fullname = fullname; HoursWorked = hoursWorked; } public decimal CalculateSalaryMonthlyInterface() { decimal hourValue = 20000M; decimal salary = hourValue * HoursWorked; return salary; } public override decimal CalculateSalaryMonthly() { decimal hourValue = 20000M; decimal salary = hourValue * HoursWorked; return salary; } } } #endregion ``` **Class EmployeeFullTime.cs** ```js #region Using an abstract class and an interface using OpenClose.Interface; namespace OpenClose { public class EmployeeFullTime : Employee, IEmployee { public EmployeeFullTime(string fullname, int hoursWorked) { Fullname = fullname; HoursWorked = hoursWorked; } public decimal CalculateSalaryMonthlyInterface() { decimal hourValue = 30000M; decimal salary = hourValue * HoursWorked; return salary; } public override decimal CalculateSalaryMonthly() { decimal hourValue = 30000M; decimal salary = hourValue * HoursWorked; return salary; } } } #endregion ``` **Class EmployeePartTime.cs** ```js #region Using an abstract class and an interface using OpenClose.Interface; namespace OpenClose { public class EmployeePartTime : Employee, IEmployee { public EmployeePartTime(string fullname, int hoursWorked) { Fullname = fullname; HoursWorked = hoursWorked; } public decimal CalculateSalaryMonthlyInterface() { decimal hourValue = 20000M; decimal salary = hourValue * HoursWorked; return salary; } public override decimal CalculateSalaryMonthly() { decimal hourValue = 20000M; decimal salary = hourValue * HoursWorked; return salary; } } } #endregion ``` **Class Program.cs** ```js using OpenClose; using OpenClose.Interface; ShowSalaryMonthly( new List<IEmployee>() { new EmployeeFullTime("Pepito Pérez", 160), new EmployeePartTime("Manuel Lopera", 180), new EmployeeContractor("Carlos Estrada", 200) }, new List<Employee>(){ new EmployeeFullTime("Pepito Pérez", 160), new EmployeePartTime("Manuel Lopera", 180), new EmployeeContractor("Carlos Estrada", 200) }); void ShowSalaryMonthly(List<IEmployee> employeesInterface, List<Employee> employeesAbstract) { Console.WriteLine("Implementación con la clase interfaz"); foreach (var employee in employeesInterface) { Console.WriteLine($"Empleado: {employee.Fullname}, pago: {employee.CalculateSalaryMonthlyInterface()}, horas trabajadas: {employee.HoursWorked}"); } Console.WriteLine("Implementación con la clase abstracta"); foreach (var employee in employeesAbstract) { Console.WriteLine($"Empleado: {employee.Fullname}, pago: {employee.CalculateSalaryMonthly()}, horas trabajadas: {employee.HoursWorked}"); } } ``` **Respuesta por consola** ![](https://static.platzi.com/media/user_upload/image-50a256d4-4452-42cc-85ec-716ba05a4da8.jpg)
La combinación de la clase teoríca y luego verlo en un ejemplo práctico es excelente para tener un mejor entendimiento, me parece excelente :D
```c# namespace OpenClose { public interface IEmployeeService { decimal CalculateSalaryMonthly(string fullname, int hoursWorked ); } } namespace OpenClose { public class EmployeeContractor : IEmployee { public decimal CalculateSalaryMonthly(string fullname, int hoursWorked) { decimal hourValue = 60000M; decimal salary = hourValue * hoursWorked; return salary; } } } ```namespace OpenClose{ public interface IEmployeeService { decimal CalculateSalaryMonthly(string fullname, int hoursWorked ); }}` public class EmployeeContractor : IEmployee { public decimal CalculateSalaryMonthly(string fullname, int hour` public class EmployeeContractor : IEmployee { public decimal CalculateSalaryMonthly(string fullname, int hoursWorked) { decimal hourValue = 60000M; decimal salary = hourValue \* hoursWorked; return salary; } }```js public class EmployeeContractor : IEmployee { public decimal CalculateSalaryMonthly(string fullname, int hoursWorked) { decimal hourValue = 60000M; decimal salary = hourValue \* hoursWorked; return salary; } } ````sWorked) { decimal hourValue = 60000M; decimal salary = hourValue \* hoursWorked; return salary; } }`

Yo pondría hourValue como propiedad en la clase abstracta y el método CalculateSalaryMonthly también, así ninguno de los que herede tiene que implementarlo. A menos que el cálculo sea diferente.

Yo creo que se puede utilizar tanto herencia como implementación, en este caso las propiedades se harian en la clase Employee y para facilitar su creación, en el constructor se inicializa y donde se herede se le aplica el “:base()”, ademas en cada tipo de contrato se implementaria la interfas IEmployee que contiene las acciones que pueden implementase diferente.
Si se repite = hereda
si se usa mucho y de forma diferente = interfaz

Este fue un ejemplo muy claro y consiso. Buena clase.

La interfaz queda de esta forma

namespace OpenClose
{
    public interface IEmployee
    {
        string Fullname
        {
            get;
            set;
        }
        int HoursWorked
        {
            get;
            set;
        }
        decimal CalculateSalaryMonthly();

    }
}

La clase EmployeeContractor queda de esta forma

namespace OpenClose
{
    public class EmployeeContractor : IEmployee
    {

        public string Fullname { get; set; }
        public int HoursWorked { get; set; }
        public EmployeeContractor(string fullName, int horas){
            Fullname = fullName;
            HoursWorked = horas;
        }
        public decimal CalculateSalaryMonthly()
        {
            decimal hourValue = 20000M;
            decimal salary = hourValue * HoursWorked;
            return salary;
        }
    }
}

Así mismo las demás clases, la implementacion en el program de esta forma.

using OpenClose;

void ShowSalaryMonthly(List<IEmployee> employees) 
{
    foreach (var employee in employees)
    {
        Console.WriteLine($"Empleado: {employee.Fullname}, Pago: {employee.CalculateSalaryMonthly():C1} ");
    }
}

ShowSalaryMonthly(new List<IEmployee>() {
    new EmployeeFullTime("Pepito Pérez", 160),
    new EmployeePartTime("Manuel Lopera", 180),
    new EmployeeContractor("Juan", 2000000)
});

Me demore bastante, pero al fin, quede satisfecho. Buena suerte

No me permite compilar