abatido y optimista


88

Soy nuevo en C # (y OOP ). Cuando tengo un código como el siguiente:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}

Pregunta 1 : Si tengo otro código que hace esto:

   Manager mgr = new Manager();
   Employee emp = (Employee)mgr;

Aquí Employeehay un Manager, pero cuando lo Employeelanzo así a un , ¿significa que lo estoy subiendo?

Pregunta 2 :

Cuando tengo varios Employeeobjetos de clase y algunos, pero no todos, son Manager, ¿cómo puedo abatirlos cuando sea posible?


6
El upcasting se puede realizar sin un elenco explícito. Entonces Employee emp= mgr;debería ser suficiente.
besarme la axila

Respuestas:


93
  1. Eso es correcto. Cuando haces eso, lo estás convirtiendo en un employeeobjeto, lo que significa que no puedes acceder a nada específico del administrador.

  2. Downcasting es donde tomas una clase básica y luego intentas convertirla en una clase más específica. Esto se puede lograr usando is y un elenco explícito como este:

    if (employee is Manager)
    {
        Manager m = (Manager)employee;
        //do something with it
    }
    

o con el asoperador así:

Manager m = (employee as Manager);
if (m != null)
{
    //do something with it
}

Si algo no está claro, estaré encantado de corregirlo.


Necesito un ejemplo para saber qué es Downcasting.
user184805

4
Evite redefinir términos bien establecidos: "boxing", en el contexto de OOP y C #, significa algo bastante diferente (= envolver un objeto de tipo de valor en una referencia). Además, su ejemplo podría (y debería) usar el asoperador en lugar de is, seguido de una conversión.
Konrad Rudolph

2
Me corrigió el primer punto y cambié la segunda mitad de mi respuesta para mostrar ambas formas de hacerlo.
RCIX

2
Su primera afirmación ("... convertir [una instancia de la clase Manager] en un objeto" empleado "[...] significa que no puede acceder a nada específico del administrador") no es completamente precisa. En el ejemplo de OP, si el Empleado tiene un miembro virtual que está anulado en Manager, el CLR llamará a la implementación de Manager, a pesar del reparto. Del artículo de MSDN sobre polimorfismo en C #: "Cuando una clase derivada reemplaza a un miembro virtual, se llama a ese miembro incluso cuando se accede a una instancia de esa clase como instancia de la clase base". El ejemplo proporcionado por MSDN es casi idéntico.
Antony

49

Upcasting (usar (Employee)someInstance) es generalmente fácil ya que el compilador puede decirle en tiempo de compilación si un tipo se deriva de otro.

Sin embargo, el downcasting debe realizarse en tiempo de ejecución, ya que es posible que el compilador no siempre sepa si la instancia en cuestión es del tipo dado. C # proporciona dos operadores para esto: es el que le dice si el abatido funciona y devuelve verdadero / falso. Y como que intenta hacer el reparto y devuelve el tipo correcto si es posible, o nulo si no.

Para probar si un empleado es gerente:

Employee m = new Manager();
Employee e = new Employee();

if(m is Manager) Console.WriteLine("m is a manager");
if(e is Manager) Console.WriteLine("e is a manager");

También puedes usar esto

Employee someEmployee = e  as Manager;
    if(someEmployee  != null) Console.WriteLine("someEmployee (e) is a manager");

Employee someEmployee = m  as Manager;
    if(someEmployee  != null) Console.WriteLine("someEmployee (m) is a manager");

11
  • Upcasting es una operación que crea una referencia de clase base a partir de una referencia de subclase. (subclase -> superclase) (es decir, Gerente -> Empleado)
  • Downcasting es una operación que crea una referencia de subclase a partir de una referencia de clase base. (superclase -> subclase) (es decir, empleado -> gerente)

En tu caso

Employee emp = (Employee)mgr; //mgr is Manager

estás haciendo un upcasting.

Un upcast siempre tiene éxito a diferencia de un downcast que requiere un cast explícito porque potencialmente puede fallar en tiempo de ejecución ( InvalidCastException ).

C # ofrece dos operadores para evitar que se lance esta excepción:

Empezando desde:

Employee e = new Employee();

Primero:

Manager m = e as Manager; // if downcast fails m is null; no exception thrown

Segundo:

if (e is Manager){...} // the predicate is false if the downcast is not possible 

Advertencia : cuando realiza una conversión ascendente, solo puede acceder a los métodos, propiedades, etc. de la superclase ...


6

En caso de que necesite verificar cada uno de los objetos Empleado si es un objeto Administrador, use el método OfType:

List<Employee> employees = new List<Employee>();

//Code to add some Employee or Manager objects..

var onlyManagers = employees.OfType<Manager>();

foreach (Manager m in onlyManagers) {
  // Do Manager specific thing..
}

2

Respuesta 1: Sí, se llama upcasting, pero la forma en que lo haces no es la forma moderna. La conversión se puede realizar implícitamente, no necesita ninguna conversión. Así que simplemente escribiendo Employee emp = mgr; es suficiente para upcasting.

Respuesta 2: Si crea un objeto de la clase Administrador, podemos decir que el administrador es un empleado. Porque la clase Manager: Employee describe la relación Is-A entre la clase de empleado y la clase de manager. Entonces podemos decir que todo gerente es un empleado.

Pero si creamos un objeto de la clase Empleado, no podemos decir que este empleado sea gerente porque la clase Empleado es una clase que no hereda ninguna otra clase. Por lo tanto, no puede rebajar directamente ese objeto Employee Class al objeto Manager Class.

Entonces, la respuesta es, si desea bajar del objeto Employee Class al objeto Manager Class, primero debe tener el objeto Manager Class primero, luego puede ascenderlo y luego puede bajarlo.


-1

Upcasting y Downcasting:

Upcasting: conversión de clase derivada a clase base Downcasting: conversión de clase base a clase derivada

Entendamos lo mismo como ejemplo:

Considere dos clases Shape como Mi clase principal y Circle como una clase derivada, definida de la siguiente manera:

class Shape
{
    public int Width { get; set; }
    public int Height { get; set; }
}

class Circle : Shape
{
    public int Radius { get; set; }
    public bool FillColor { get; set; }
}

Upcasting:

Forma s = nueva Forma ();

Círculo c = s;

Ambos cys hacen referencia a la misma ubicación de memoria, pero ambos tienen vistas diferentes, es decir, utilizando la referencia "c" puede acceder a todas las propiedades de la clase base y la clase derivada también, pero utilizando la referencia "s" puede acceder a las propiedades de la única clase padre.

Un ejemplo práctico de upcasting es la clase Stream, que es la clase base de todos los tipos de lectores de stream de .net framework:

Lector StreamReader = nuevo StreamReader (nuevo FileStreamReader ());

aquí, FileStreamReader () se actualiza a streadm reder.

Abatimiento:

Forma s = new Circle (); aquí, como se explicó anteriormente, la vista de s es el único padre, para que sea tanto para el padre como para el niño, debemos abatirlo

var c = (Círculo) s;

El ejemplo práctico de Downcasting es la clase de botón de WPF.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.