Comenzaremos distinguiendo entre empleados y cónyuges por diferentes clases, en lugar de hacerlo estrictamente por la propiedad del tipo de usuario. Si vamos a tener una clase de Empleado y una clase de Cónyuge y compartimos mucho código entre ellos, nuestro primer instinto es copiar y pegar ese código. En lugar de hacer eso literalmente, vamos a copiar y pegar de una manera agradable, orientada a objetos, creando un nuevo objeto Cónyuge que herede del objeto Empleado:
12345clase públicaEsposo:Empleado{}
csharp
Eso es todo. En este punto, tenemos un objeto separado que refleja mucho mejor el modelo, distinguiendo que el usuario no es un empleado del tipo Cónyuge, lo cual no es cierto, sino que es un usuario del tipo Cónyuge, el cual – en este punto – tiene todos los privilegios y el poder de un empleado del tipo usuario.
Antes mencionamos que tenemos la lógica condicional esparcida por todo el código, tal vez en una forma como esta:
1234567891011121314151617switch(user.UserType){case UserTypes.Employee:// do employee-oriented stuffbreak;case UserTypes.Spouse:// do spouse-oriented stuffbreak;}
csharp
Ahora que nos estamos moviendo hacia un modelo heredado adecuado, conseguiremos que se refactorice – eventualmente. Pero por el momento, queremos que nuestras nuevas clases reflejen su tipo de usuario automáticamente. Para ello, cambiaremos la propiedad UserType de la clase base Employee de una propiedad respaldada automáticamente, a simplemente devolver «Employee» como su tipo de usuario:
1234567///<resumen;//// El tipo de usuario actual.///</resumen;Debido a que el Cónyuge hereda del Empleado, esto significa que sin ningún cambio, los Cónyuges serían tratados como Empleados. Debido a esto, hemos añadido la palabra clave virtual - esto marca la propiedad o método como elegible para ser anulado. Anularemos la propiedad en nuestra clase de Cónyuge de esta manera:
1publicoverrideUserTypes UserTypes.Spouse;csharp
Simple. Nuestra lógica condicional dispersa seguirá funcionando hasta que podamos consolidarla. Ahora, sobre el método Save - queremos dividir las dos ramas en llamadas separadas en objetos separados. Empezamos modificando la llamada Save() del empleado de esta manera:
1234567publicvoidSave(){// la lógica de persistencia real va aquí}csharp
En esta llamada, haríamos la persistencia real al almacén de datos. Luego añadimos el siguiente código a la clase de Cónyuge:
123456789public newvoid Save(){/// enviar la solicitud a la Administración// que obtendrá la autorización del empleado para el cambio}csharp
Hemos movido el código de notificación y autorización del administrador a esta clase. Tened en cuenta que en lugar de override aquí en el método hijo, ahora estoy usando nuevo , y además no he añadido la palabra clave virtual al método base. Este es a veces el enfoque que quieres tomar por razones de orientación a objetos, particularmente porque puede que no tengas ACCESO al método base, como cuando heredas de una clase en un marco de trabajo que no controlas. Cuando utilizamos este enfoque, con la nueva palabra clave en un método de una clase que hereda, esto se llama ocultar .
¿Cuál es la diferencia? Ambos parecen anular el método Save, al menos en un sentido informal. La diferencia está en cómo se resuelve una llamada a Save(). En el siguiente código:
123var cónyuge =nuevoCónyuge();((Empleado)cónyuge).Save();csharp
Estamos instanciando un objeto del Cónyuge, pero luego lo lanzamos a la clase de empleados de la base para llamar a Save. En este caso, con el enfoque de ocultar, se llama al método Save de la clase de empleado base, NO al nuevo método Save del Cónyuge . Si en cambio, lo anulamos con la palabra clave virtual de la clase base, este mismo código llamaría al método de anulación del Cónyuge. En resumen - La diferencia entre anular y ocultar es cómo se resuelven las llamadas a los métodos. Ten en cuenta esta diferencia al hacer tus elecciones de modelado.