Programación Orientada A Objetos (C#) - Microsoft Docs

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 12

19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

Docs ​/
.NET ​/
Guía de C# ​/
Aspectos básicos ​/ 1  

Programación orientada a objetos (C#)


Artículo • 10/05/2022 • Tiempo de lectura: 12 minutos • 1 colaborador  

En este artículo
Creación de diferentes tipos de cuentas
Diferentes reglas de descubierto
Resumen

C# es un lenguaje de programación orientado a objetos. Los cuatro principios básicos de


la programación orientada a objetos son:

Abstracción: modelar los atributos e interacciones pertinentes de las entidades como


clases para definir una representación abstracta de un sistema.
Encapsulación: ocultar el estado interno y la funcionalidad de un objeto y permitir
solo el acceso a través de un conjunto público de funciones.
Herencia: capacidad de crear nuevas abstracciones basadas en abstracciones
existentes.
Polimorfismo: capacidad de implementar propiedades o métodos heredados de
maneras diferentes en varias abstracciones.

En el tutorial anterior, Introducción a las clases se trató la abstracción y la encapsulación.


La clase BankAccount proporcionó una abstracción para el concepto de una cuenta
bancaria. Puede modificar su implementación sin que afecte para nada al código que usó
la clase BankAccount . Las clases BankAccount y Transaction proporcionan
encapsulación de los componentes necesarios para describir esos conceptos en el código.

En este tutorial, ampliará la aplicación para hacer uso de la herencia y el polimorfismo


para agregar nuevas características. También agregará características a la clase
BankAccount , aprovechando las técnicas de abstracción y encapsulación que aprendió en

el tutorial anterior.

Creación de diferentes tipos de cuentas


Después de compilar este programa, recibirá solicitudes para agregarle características.
Funciona bien en situaciones en las que solo hay un tipo de cuenta bancaria. Con el
tiempo, las necesidades cambian y se solicitan tipos de cuenta relacionados:

https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 1/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

Una cuenta que devenga intereses que genera beneficios al final de cada mes.
Una línea de crédito que puede tener un saldo negativo, pero cuando sea así, se
producirá un cargo por intereses cada mes.
Una cuenta de tarjeta de regalo de prepago que comienza con un único depósito y
solo se puede liquidar. Se puede recargar una vez al principio de cada mes.

Todas estas cuentas diferentes son similares a la clase BankAccount definida en el tutorial
anterior. Podría copiar ese código, cambiar el nombre de las clases y realizar
modificaciones. Esa técnica funcionaría a corto plazo, pero a la larga supondría más
trabajo. Cualquier cambio se copiará en todas las clases afectadas.

En su lugar, puede crear nuevos tipos de cuenta bancaria que hereden métodos y datos
de la clase BankAccount creada en el tutorial anterior. Estas clases nuevas pueden
extender la clase BankAccount con el comportamiento específico necesario para cada
tipo:

C# = Copiar

public class InterestEarningAccount : BankAccount


{
}

public class LineOfCreditAccount : BankAccount


{
}

public class GiftCardAccount : BankAccount


{
}

Cada una de estas clases hereda el comportamiento compartido de su clase base


compartida, la clase BankAccount . Escriba las implementaciones para la funcionalidad
nueva y diferente en cada una de las clases derivadas. Estas clases derivadas ya tienen
todo el comportamiento definido en la clase BankAccount .

Es recomendable crear cada clase nueva en un archivo de código fuente diferente. En


Visual Studio , puede hacer clic con el botón derecho en el proyecto y seleccionar
Agregar clase para agregar una clase nueva en un archivo nuevo. En Visual Studio
Code , seleccione Archivo y luego Nuevo para crear un nuevo archivo de código fuente.
En cualquier herramienta, ponga un nombre al archivo que coincida con la clase:
InterestEarningAccount.cs, LineOfCreditAccount.cs y GiftCardAccount.cs.

Cuando cree las clases como se muestra en el ejemplo anterior, observará que ninguna
de las clases derivadas se compila. La inicialización de un objeto es responsabilidad de un
constructor. Un constructor de clase derivada debe inicializar la clase derivada y
https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 2/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

proporcionar instrucciones sobre cómo inicializar el objeto de la clase base incluido en la


clase derivada. Normalmente, se produce una inicialización correcta sin ningún código
adicional. La clase BankAccount declara un constructor público con la siguiente firma:

C# = Copiar

public BankAccount(string name, decimal initialBalance)

El compilador no genera un constructor predeterminado al definir un constructor. Esto


significa que cada clase derivada debe llamar explícitamente a este constructor. Se declara
un constructor que puede pasar argumentos al constructor de la clase base. En el código
siguiente se muestra el constructor de InterestEarningAccount :

C# = Copiar

public InterestEarningAccount(string name, decimal initialBalance) :


base(name, initialBalance)
{
}

Los parámetros de este nuevo constructor coinciden con el tipo de parámetro y los
nombres del constructor de clase base. Utilice la sintaxis de : base() para indicar una
llamada a un constructor de clase base. Algunas clases definen varios constructores, y
esta sintaxis le permite elegir el constructor de clase base al que llama. Una vez que haya
actualizado los constructores, puede desarrollar el código para cada una de las clases
derivadas. Los requisitos para las clases nuevas se pueden indicar de la siguiente manera:

Una cuenta que devenga intereses:


obtendrá un crédito del 2 % del saldo a final de mes.
Una línea de crédito:
puede tener un saldo negativo, pero no mayor en valor absoluto que el límite de
crédito.
Generará un cargo por intereses cada mes en el que el saldo final del mes no sea
0.
Generará un cargo por cada retirada que supere el límite de crédito.
Una cuenta de tarjeta regalo:
Se puede recargar con una cantidad especificada una vez al mes, el último día del
mes.

Puede ver que los tres tipos de cuenta tienen una acción que tiene lugar al final de cada
mes. Sin embargo, cada tipo de cuenta realiza diferentes tareas. Utiliza el polimorfismo
para implementar este código. Cree un método virtual único en la clase BankAccount :

https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 3/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

C# = Copiar

public virtual void PerformMonthEndTransactions() { }

El código anterior muestra cómo se usa la palabra clave virtual para declarar un
método en la clase base para el que una clase derivada puede proporcionar una
implementación diferente. Un método virtual es un método en el que cualquier clase
derivada puede optar por volver a implementar. Las clases derivadas usan la palabra
clave override para definir la nueva implementación. Normalmente, se hace referencia a
este proceso como "reemplazar la implementación de la clase base". La palabra clave
virtual especifica que las clases derivadas pueden invalidar el comportamiento.

También puede declarar métodos abstract en los que las clases derivadas deben
reemplazar el comportamiento. La clase base no proporciona una implementación para
un método abstract . A continuación, debe definir la implementación de dos de las
nuevas clases que ha creado. Empiece por InterestEarningAccount :

C# = Copiar

public override void PerformMonthEndTransactions()


{
if (Balance > 500m)
{
decimal interest = Balance * 0.05m;
MakeDeposit(interest, DateTime.Now, "apply monthly interest");
}
}

Agregue el código siguiente a LineOfCreditAccount . El código niega el saldo para


calcular un cargo de interés positivo que se retira de la cuenta:

C# = Copiar

public override void PerformMonthEndTransactions()


{
if (Balance < 0)
{
// Negate the balance to get a positive interest charge:
decimal interest = -Balance * 0.07m;
MakeWithdrawal(interest, DateTime.Now, "Charge monthly
interest");
}
}

La clase GiftCardAccount necesita dos cambios para implementar su funcionalidad de


fin de mes. En primer lugar, modifique el constructor para incluir una cantidad opcional
https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 4/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

para agregar cada mes:

C# = Copiar

private readonly decimal _monthlyDeposit = 0m;

public GiftCardAccount(string name, decimal initialBalance, decimal


monthlyDeposit = 0) : base(name, initialBalance)
=> _monthlyDeposit = monthlyDeposit;

El constructor proporciona un valor predeterminado para el valor monthlyDeposit , por lo


que los llamadores pueden omitir 0 para ningún ingreso mensual. A continuación,
invalide el método PerformMonthEndTransactions para agregar el depósito mensual, si
se estableció en un valor distinto de cero en el constructor:

C# = Copiar

public override void PerformMonthEndTransactions()


{
if (_monthlyDeposit != 0)
{
MakeDeposit(_monthlyDeposit, DateTime.Now, "Add monthly
deposit");
}
}

La invalidación aplica el conjunto de depósitos mensual en el constructor. Agregue el


código siguiente al método Main para probar estos cambios en GiftCardAccount y en
InterestEarningAccount :

C# = Copiar

var giftCard = new GiftCardAccount("gift card", 100, 50);


giftCard.MakeWithdrawal(20, DateTime.Now, "get expensive coffee");
giftCard.MakeWithdrawal(50, DateTime.Now, "buy groceries");
giftCard.PerformMonthEndTransactions();
// can make additional deposits:
giftCard.MakeDeposit(27.50m, DateTime.Now, "add some additional spending
money");
Console.WriteLine(giftCard.GetAccountHistory());

var savings = new InterestEarningAccount("savings account", 10000);


savings.MakeDeposit(750, DateTime.Now, "save some money");
savings.MakeDeposit(1250, DateTime.Now, "Add more savings");
savings.MakeWithdrawal(250, DateTime.Now, "Needed to pay monthly bills");
savings.PerformMonthEndTransactions();
Console.WriteLine(savings.GetAccountHistory());

https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 5/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

Verifique los resultados. Ahora, agregue un conjunto similar de código de prueba para
LineOfCreditAccount :

= Copiar

var lineOfCredit = new LineOfCreditAccount("line of credit", 0);


// How much is too much to borrow?
lineOfCredit.MakeWithdrawal(1000m, DateTime.Now, "Take out monthly
advance");
lineOfCredit.MakeDeposit(50m, DateTime.Now, "Pay back small amount");
lineOfCredit.MakeWithdrawal(5000m, DateTime.Now, "Emergency funds for
repairs");
lineOfCredit.MakeDeposit(150m, DateTime.Now, "Partial restoration on
repairs");
lineOfCredit.PerformMonthEndTransactions();
Console.WriteLine(lineOfCredit.GetAccountHistory());

Al agregar el código anterior y ejecutar el programa, verá algo parecido al siguiente error:

Consola = Copiar

Unhandled exception. System.ArgumentOutOfRangeException: Amount of depo‐


sit must be positive (Parameter 'amount')
at OOProgramming.BankAccount.MakeDeposit(Decimal amount, DateTime
date, String note) in BankAccount.cs:line 42
at OOProgramming.BankAccount..ctor(String name, Decimal initialBa‐
lance) in BankAccount.cs:line 31
at OOProgramming.LineOfCreditAccount..ctor(String name, Decimal
initialBalance) in LineOfCreditAccount.cs:line 9
at OOProgramming.Program.Main(String[] args) in Program.cs:line 29

7 Nota

La salida real incluye la ruta de acceso completa a la carpeta con el proyecto. Los
nombres de carpeta se omitieron para ser más breves. Además, dependiendo del
formato del código, los números de línea pueden ser ligeramente diferentes.

Este código produce un error porque BankAccount supone que el saldo inicial debe ser
mayor que 0. Otra suposición incorporada en la clase BankAccount es que el saldo no
puede entrar en cifras negativas. Lo que sucede que es se rechazan las retiradas que
provocan un descubierto en la cuenta. Ambas suposiciones deben cambiar. La línea de la
cuenta de crédito comienza en 0, y generalmente tendrá un saldo negativo. Además, si un
cliente retira demasiado dinero, generará un cargo. La transacción se acepta, solo que
cuesta más. La primera regla se puede implementar agregando un argumento opcional al
constructor BankAccount que especifica el saldo mínimo. El valor predeterminado es 0 .

https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 6/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

La segunda regla requiere un mecanismo que permita que las clases derivadas
modifiquen el algoritmo predeterminado. En cierto sentido, la clase base "pregunta" al
tipo derivado qué debe ocurrir cuando hay un descubierto. El comportamiento
predeterminado es rechazar la transacción generando una excepción.

Comencemos agregando un segundo constructor que incluya un parámetro


minimumBalance opcional. Este nuevo constructor se ocupa de todas las acciones que

realiza el constructor existente. Además, establece la propiedad del saldo mínimo. Podría
copiar el cuerpo del constructor existente. Sin embargo, esto implica que dos ubicaciones
cambiarán en el futuro. Lo que puede hacer es usar un encadenamiento de constructores
para que un constructor llame a otro. En el código siguiente se muestran los dos
constructores y el nuevo campo adicional:

C# = Copiar

private readonly decimal _minimumBalance;

public BankAccount(string name, decimal initialBalance) : this(name,


initialBalance, 0) { }

public BankAccount(string name, decimal initialBalance, decimal minimum‐


Balance)
{
Number = s_accountNumberSeed.ToString();
s_accountNumberSeed++;

Owner = name;
_minimumBalance = minimumBalance;
if (initialBalance > 0)
MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
}

En el código anterior se muestran dos técnicas nuevas. En primer lugar, el campo


minimumBalance está marcado como readonly . Esto significa que el valor no se puede
cambiar después de que se construya el objeto. Una vez que se crea BankAccount ,
minimumBalance no puede cambiar. En segundo lugar, el constructor que toma dos

parámetros utiliza : this(name, initialBalance, 0) { } como su implementación. La


expresión : this() llama al otro constructor, el que tiene tres parámetros. Esta técnica
permite tener una única implementación para inicializar un objeto, aunque el código de
cliente puede elegir uno de muchos constructores.

Esta implementación solo llama a MakeDeposit si el saldo inicial es mayor que 0 . Esto
conserva la regla de que los depósitos deben ser positivos, pero permite que la cuenta de
crédito se abra con un saldo de 0 .

https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 7/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

Ahora que la clase BankAccount tiene un campo de solo lectura para el saldo mínimo, el
último cambio es modificar la codificación rígida 0 a minimumBalance en el método
MakeWithdrawal :

C# = Copiar

if (Balance - amount < minimumBalance)

Después de extender la clase BankAccount , puede modificar el constructor


LineOfCreditAccount para llamar al nuevo constructor base, como se muestra en el

código siguiente:

C# = Copiar

public LineOfCreditAccount(string name, decimal initialBalance, decimal


creditLimit) : base(name, initialBalance, -creditLimit)
{
}

Observe que el constructor LineOfCreditAccount cambia el signo del parámetro


creditLimit para que coincida con el significado del parámetro minimumBalance .

Diferentes reglas de descubierto


La última característica que se va a agregar permite a LineOfCreditAccount cobrar una
cuota por sobrepasar el límite de crédito en lugar de rechazar la transacción.

Una técnica consiste en definir una función virtual en la que se implemente el


comportamiento requerido. La clase BankAccount refactoriza el método MakeWithdrawal
en dos métodos. El nuevo método realiza la acción especificada cuando la retirada toma el
saldo por debajo del mínimo. El método MakeWithdrawal existente tiene el siguiente
código:

C# = Copiar

public void MakeWithdrawal(decimal amount, DateTime date, string note)


{
if (amount <= 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "Amount of
withdrawal must be positive");
}
if (Balance - amount < minimumBalance)
{

https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 8/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

throw new InvalidOperationException("Not sufficient funds for


this withdrawal");
}
var withdrawal = new Transaction(-amount, date, note);
allTransactions.Add(withdrawal);
}

Reemplácelo por el código siguiente:

C# = Copiar

public void MakeWithdrawal(decimal amount, DateTime date, string note)


{
if (amount <= 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "Amount of
withdrawal must be positive");
}
Transaction? overdraftTransaction = CheckWithdrawalLimit(Balance -
amount < _minimumBalance);
Transaction? withdrawal = new(-amount, date, note);
_allTransactions.Add(withdrawal);
if (overdraftTransaction != null)
_allTransactions.Add(overdraftTransaction);
}

protected virtual Transaction? CheckWithdrawalLimit(bool isOverdrawn)


{
if (isOverdrawn)
{
throw new InvalidOperationException("Not sufficient funds for
this withdrawal");
}
else
{
return default;
}
}

El método agregado es protected , lo que significa que solo se puede llamar desde clases
derivadas. Esa declaración impide que otros clientes llamen al método. También es
virtual para que las clases derivadas puedan cambiar el comportamiento. El tipo de

valor devuelto es Transaction? . La anotación ? indica que el método puede devolver


null . Agregue la siguiente implementación en LineOfCreditAccount para cobrar una

cuota cuando se supere el límite de retirada:

C# = Copiar

protected override Transaction? CheckWithdrawalLimit(bool isOverdrawn) =>


isOverdrawn
https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 9/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

? new Transaction(-20, DateTime.Now, "Apply overdraft fee")


: default;

El reemplazo devuelve una transacción de cuota cuando en la cuenta se produce un


descubierto. Si la retirada no supera el límite, el método devuelve una transacción null .
Esto indica que no hay ninguna cuota. Pruebe estos cambios agregando el código
siguiente al método Main en la clase Program :

C# = Copiar

var lineOfCredit = new LineOfCreditAccount("line of credit", 0, 2000);


// How much is too much to borrow?
lineOfCredit.MakeWithdrawal(1000m, DateTime.Now, "Take out monthly ad‐
vance");
lineOfCredit.MakeDeposit(50m, DateTime.Now, "Pay back small amount");
lineOfCredit.MakeWithdrawal(5000m, DateTime.Now, "Emergency funds for re‐
pairs");
lineOfCredit.MakeDeposit(150m, DateTime.Now, "Partial restoration on re‐
pairs");
lineOfCredit.PerformMonthEndTransactions();
Console.WriteLine(lineOfCredit.GetAccountHistory());

Ejecute el programa y compruebe los resultados.

Resumen
Si se ha quedado bloqueado, puede consultar el origen de este tutorial en el repositorio
de GitHub .

En este tutorial se han mostrado muchas de las técnicas que se usan en la programación
orientada a objetos:

Usó la abstracción cuando definió clases para cada uno de los distintos tipos de
cuenta. Esas clases describían el comportamiento de ese tipo de cuenta.
Usó la encapsulación cuando mantuvo muchos detalles private en cada clase.
Usó la herencia cuando aprovechó la implementación ya creada en la clase
BankAccount para guardar el código.

Usó el polimorfismo cuando creó métodos virtual que las clases derivadas
podrían reemplazar para crear un comportamiento específico para ese tipo de
cuenta.

Contenido recomendado
https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 10/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

Un paseo por C#: tipos y sus miembros


Los bloques de creación de los programas son los tipos. Aprenda a crear clases, estructuras,
interfaces y mucho más en C#.

Un paseo por C#: información general


¿Nuevo en C#? Conozca los conceptos básicos del lenguaje. Comience con esta información
general.

Guía de programación de C#
Utilice estos recursos para obtener información detallada sobre las funcionalidades y
características claves del lenguaje C# a las que C# puede acceder a través de .NET.

Clases y objetos: tutorial de aspectos básicos de C#


Creación del primer programa con C# y análisis de los conceptos orientados a objetos

Estructura general de un programa de C#


Aprenda sobre la estructura de un programa de C# mediante un programa esqueleto que
contiene todos los elementos necesarios para un programa.

Conceptos de programación (C#)


Use los recursos de esta sección para comprender los conceptos de programación del
lenguaje C#, incluida la programación orientada a objetos.

Clases, estructuras y registros en C #


Describe el uso de clases, estructuras (struct) y registros en C#.

Ramas y bucles: tutorial de introducción a C#


En este tutorial sobre ramas y bucles, escribirá código de C# para explorar la sintaxis del
lenguaje que admite ramas y bucles condicionales para ejecutar instrucciones de forma
repetida.

Mostrar más S

https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 11/12
19/5/22, 19:20 Programación orientada a objetos (C#) | Microsoft Docs

https://docs.microsoft.com/es-es/dotnet/csharp/fundamentals/tutorials/oop 12/12

También podría gustarte