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 17

Preguntas 4

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

La respuesta del reto implementando la 鈥渋nterface鈥

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/

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)
});

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;
        }
    }
}
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