Pregunta

No estoy seguro de si esto es una cosa extraña que hacer o no, o si es de alguna forma el código de olor...pero me preguntaba si había una manera de (algún tipo de programación orientada a objetos patrón sería bueno) para "lanzar" un tipo de base a un formulario de su tipo derivado.Sé que esto tiene poco sentido como el tipo derivado tendrá una funcionalidad adicional que el padre no está de oferta, la cual es en su auto, no el sonido fundamental.Pero, ¿hay alguna manera de hacer esto?Aquí está un ejemplo de código para que así yo pueda explicar mejor lo que estoy pidiendo.

public class SomeBaseClass {
    public string GetBaseClassName {get;set;}
    public bool BooleanEvaluator {get;set;}
}

public class SomeDerivedClass : SomeBaseClass {
    public void Insert(SqlConnection connection) {
          //...random connection stuff
          cmd.Parameters["IsItTrue"].Value = this.BooleanEvalutar;
          //...
    }
}

public static void Main(object[] args) {
    SomeBaseClass baseClass = new SomeBaseClass();
    SomeDerivedClass derClass = (SomeDerivedClass)baseClass; 
    derClass.Insert(new sqlConnection());
}

Sé que esto parece torpe pero ¿hay alguna manera de lograr algo de este tipo?

¿Fue útil?

Solución

No profundamente, en la "gestión" de los idiomas.Este es downcasting, y no hay ninguna cuerda hacia abajo de manera de manejarlo, por exactamente la razón por la que usted describe (subclases proporcionar más de la base de clases - ¿de dónde viene este "más" vienen?).Si usted realmente desea un comportamiento similar de una determinada jerarquía, puede utilizar los constructores de tipos derivados que tomará el tipo base de un prototipo.

Uno podría construir algo con la reflexión que maneja los casos simples (tipos más específicos que no tienen, además del estado).En general, sólo el rediseño de evitar el problema.

Editar:Woops, no puede escribir operadores de conversión entre la base de los tipos derivados.Una rareza de Microsoft tratando de "proteger" contra ti mismo.Ah, bueno, al menos están en ninguna parte cerca tan malo como el Sol.

Otros consejos

Trate de composición en lugar de la herencia!

Esto me parece que sería mejor que pasar una instancia de SomeBaseClass a la SomeDerivedClass (que ya no se derivan de la clase base, y debe ser el nombre como tal)

public class BooleanHolder{       
    public bool BooleanEvaluator {get;set;}
}

public class DatabaseInserter{
    BooleanHolder holder;

    public DatabaseInserter(BooleanHolder holder){
        this.holder = holder;
    }

    public void Insert(SqlConnection connection) {
          ...random connection stuff
          cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
          ...
    }
}

public static void Main(object[] args) {
    BooleanHolder h = new BooleanHolder();
    DatabaseInserter derClass = new DatabaseInserter(h);
    derClass.Insert(new sqlConnection);
}

Echa un vistazo http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html (página 3):

La reutilización de código a través de la composición de la Composición ofrece una manera alternativa de Apple la reutilización de la Fruta de la aplicación de peel().En lugar de ampliar la Fruta, Apple puede contener una referencia a una Fruta instancia y definir su propia cáscara() método que simplemente invoca la cáscara() en el Fruto.

Personalmente creo que no vale la pena la molestia de usar la Herencia en este caso.En lugar de simplemente pasar a la instancia de clase base en el constructor y el acceso a ella a través de un miembro de la variable.

private class ExtendedClass //: BaseClass - like to inherit but can't
{
    public readonly BaseClass bc = null;
    public ExtendedClass(BaseClass b)
    {
        this.bc = b;
    }

    public int ExtendedProperty
    {
        get
        {
        }
    }
}

Downcasting tiene sentido, si se tiene un Objeto de clase derivada, pero es la que hace referencia una referencia de un tipo de clase base y, por alguna razón, desea volver a hacer referencia a una clase derivada de tipo de referencia.En otras palabras, Se puede abatido para revertir el efecto de la anterior upcasting.Pero Usted no puede tener un objeto de la clase base que hace referencia una referencia de una clase derivada de tipo.

No estoy diciendo que yo recomiendo este.Pero se puede dar la clase base en cadena JSON y, a continuación, convertir a la clase derivada.

SomeDerivedClass layer = JsonConvert.DeserializeObject<SomeDerivedClass>(JsonConvert.SerializeObject(BaseClassObject));

No, esto no es posible.En un lenguaje como C#, simplemente no funciona.El tiempo de ejecución no se permiten, incluso si el compilador permite que a través de ella.

Usted mismo ha dicho que esto parece goofy:

SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class; 

Por lo tanto, preguntarse, es class en realidad una instancia de SomeDerivedClass?No, por lo que la conversión no tiene sentido.Si usted necesita para convertir SomeBaseClass a SomeDerivedClass, entonces usted debe proporcionar algún tipo de conversión, un constructor o un método de conversión.

Parece como si su clase de la jerarquía de necesidades de un poco de trabajo, sin embargo.En general, no de ser posible convertir una instancia de clase base en una clase derivada de la instancia.No debe ser, en general datos y/o funcionalidad que no se aplican a la clase base.Si la clase derivada funcionalidad se aplica a todos las instancias de la clase base, entonces debe ser enrollada en la base de la clase, o tirado en una nueva clase que no es parte de la clase base de la jerarquía.

El lenguaje C# no permite este tipo de operadores, pero todavía se puede escribir de ellos y de trabajo:

[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) { ... }

[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) { ... }

Sí - esto es un código de olor, y bastante uñas el hecho de que su herencia cadena se rompe.

Mi supongo (a partir de la limitada muestra) es que prefieres tener DerivedClass operar en una instancia de SomeBaseClass - de modo que "DerivedClass tiene un SomeBaseClass", en lugar de "DerivedClass es un SomeBaseClass".Esto se conoce como "a favor de composición a lo largo de la herencia".

Como otros han señalado, el casting que sugieren que no es realmente posible.Sería tal vez sea un caso en el que el Patrón decorador(La cabeza del Primer extracto) puede ser introducido?

¿Has pensado en una interfaz que lo que es actualmente su clase base y la clase derivada tanto de implementar?No sé los detalles de por qué se está implementando de esta manera, pero podría funcionar.

Esto se llama downcasting y Seldaek la sugerencia de utilizar la "caja fuerte" de la versión es el sonido.

He aquí una bastante decente descripción con ejemplos de código.

Esto no es posible, porque ¿cómo vas a conseguir el "extra" que la clase derivada tiene.Cómo sería el compilador sabe que significa derivedClass1 y no derivedClass2 al crear instancias de ella?

Creo que lo que realmente estás buscando es el patrón de fábrica o similar, así que usted puede crear instancias de objetos sin saber realmente el tipo explícito que se instancian.En su ejemplo, tener la "Insertar" método sería una interfaz que instancia de la fábrica devuelve implementa.

No sé por qué nadie lo ha dicho y yo puede que pierdas algo, pero no se puede utilizar la palabra clave as y si usted necesita para hacer una declaración de si el uso de si.

SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
    ;

-editar- Hice esta pregunta hace mucho tiempo

He estado recientemente en la necesidad de extender una simple DTO con un tipo derivado en el fin de poner un poco mas de propiedades en ella.Yo quería volver a utilizar una lógica de conversión que yo tenía, de los tipos de base de datos para el Dto.

La forma en que lo resuelto fue imponiendo un constructor vacío en el DTO clases, utilizando como este:

class InternalDbType {
    public string Name { get; set; }
    public DateTime Date { get; set; }
    // Many more properties here...
}

class SimpleDTO {
    public string Name { get; set; }
    // Many more properties here...
}

class ComplexDTO : SimpleDTO {
    public string Date { get; set; }
}

static class InternalDbTypeExtensions {
    public static TDto ToDto<TDto>(this InternalDbType obj) where TDto : SimpleDTO, new() {
        var dto = new TDto {
            Name = obj.Name
        }
    }
}

Me puede reutilizar la lógica de conversión de la simple DTO cuando la conversión de hasta el más complejo.Por supuesto, voy a tener que llenar en las propiedades del tipo complejo en alguna otra manera, pero con muchas, muchas de las propiedades de la simple DTO, esto realmente simplifica las cosas de la OMI.

Que no puede trabajar.Mira en la página de ayuda vinculada por el error de compilación.

La mejor solución es el uso de métodos de fábrica aquí.

Como muchas de las respuestas han señalado, no se puede abatido que hace total sentido.

Sin embargo, en su caso, SomeDerivedClass no tiene propiedades que será 'falta'.Así que usted podría crear un método de extensión como esta:

public static T ToDerived<T>(this SomeBaseClass baseClass) 
    where T:SomeBaseClass, new()
{
    return new T()
    {
        BooleanEvaluator = baseClass.BooleanEvaluator,
        GetBaseClassName = baseClass.GetBaseClassName
    };
}

Así que usted no está colada, sólo la conversión:

SomeBaseClass b = new SomeBaseClass();
SomeDerivedClass c = b.ToDerived<SomeDerivedClass>();

Esto sólo funciona si todos los datos en la base de la clase es en la forma de lectura y escritura de las propiedades.

C++ maneja mediante un constructor. C++ Typecasting.Parece un descuido para mí.Muchos de ustedes han traído a colación el tema de lo que sería el proceso de hacer con las propiedades adicionales.Yo diría, lo que hace el compilador de hacer cuando se crea la clase derivada cuando el programador no establecer las propiedades?He manejado esta situación similar a la de C++.Puedo crear un constructor que toma la clase base manualmente, a continuación, establezca las propiedades en el constructor.Este es sin duda preferible a la configuración de una variable en la clase derivada y de la ruptura de la herencia.También me gustaría optar por un método de fábrica porque creo que el código resultante sería más limpio buscando.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top