2012-06-13 9 views
5

Este problema ha sido activado/desactivado y he escrito 4 wrappers ahora. Estoy seguro de que lo estoy haciendo mal y necesito descubrir dónde se está diversificando mi comprensión.C# base inheritance

Digamos que estoy usando la clase Rectángulo para representar barras de metal. (Esto funciona mejor que los animales)

Digamos que la clase base se llama "Barra".

private class Bar 
{ 
    internal Rectangle Area; 
} 

So. Ahora hacemos un rectángulo, digamos 300 unidades por 10 unidades.

private Bar CreateBar() 
{ 
    Bar1 = new Bar1(); 
    Bar1.Area = new Rectangle(new Point(0,0), new Size(300,10)); 
    return Bar1; 
} 

Fantástico, entonces tenemos una barra base.

Ahora digamos que queremos hacer que esta barra tenga un material, digamos acero. Asi que. . .

private class SteelBar : Bar 
{ 
    string Material; 
} 

Así que si lo hice. . .

private SteelBar CreateSteelBar() 
{ 
    SteelBar SteelB = new SteelB(); 
    Bar B = CreateBar(); 
    SteelB = B; 
    SteelB.Material = "Steel"; 
    return SteelB; 
} 

De lo que me sale de este si llamo CreateSteelBar, se crea un steelbar que llama CreateBar. Así que termino con una barra de acero con un rectángulo de 300 por 10 y una cuerda anulada o vacía para el material. Luego configuro el material en acero.

Cuando intento algo similar en mi programa, sigue diciendo que no puedo crear implícitamente una clase superior de una clase más abajo. Me habría imaginado que esta es la razón por la que existe la herencia teniendo en cuenta todos los heredos de los ejemplos de animales que veo, pero espero que alguien me aclare.

Además, estoy seguro de que podría llamar al SteelBar = CreateBar(); pero lo hice por el camino largo aquí.

+3

No tengo claro por qué no está utilizando constructores. Eso simplificaría su problema considerablemente. –

+0

No devuelve el valor en 'CreateBar()' –

+0

En este caso, en mi sistema, estoy creando una extensión para algo que tiene entre 1 y 500 elementos dentro de ella. – Charles

Respuesta

16

En lugar de tener un método (CreateBar), tendrá que utilizar un constructor :

public Bar() 
{ 
    this.Area = new Rectangle(new Point(0,0), new Size(300,10)); 
} 

Luego, en SteelBar, que se podría llamar el constructor de la clase base:

public SteelBar() 
{ 
    this.Material = "Steel"; 
} 

El constructor de la clase base ocurrirá primero, por lo que su área ya estará configurada. Puede ser explícito acerca de esto, sin embargo, y mostrarlo en su código:

public SteelBar() 
    : base() 
{ 
    this.Material = "Steel"; 
} 

Sin embargo, esto se suelen utilizar si usted quiere tener un constructor específico que toma argumentos.

Para obtener más información, consulte Constructors en la guía de programación C#.

+0

Esto es, de hecho, cómo se lograría el resultado deseado, como se indica en la pregunta – Nevyn

+6

@KyleTrauberman Eso es falso: el constructor de la clase base ** siempre ** se llama implícitamente. Solo necesita especificarlo si desea llamar a un constructor que no sea el constructor sin parámetros predeterminado. No hay forma de construir una subclase sin llamar a uno de los constructores de la clase base. –

+0

Tienes razón. Siempre lo llamé explícitamente. –

0

No se puede hacer esto:

SteelBar = B; 

Usted ha creado un nuevo objeto de tipo barra y que está tratando de asignar a una referencia de tipo SteelBar.

0

Estoy bastante seguro de que su problema es que usted está tratando de conversión hacia arriba:

Bar B = CreateBar(); 
SteelBar = B; 

Esto no está bien, porque a pesar SteelBar debe ser del tipo Bar (ya que heredó de) el mismo no se puede hecho al revés

Lo contrario sería legal:

SteelBar B = CreateBar(); 
Bar = (Bar)B; 

Sencillamente que está intentando almacenar una referencia de SteelBar en Bar, mientras que posiblemente podría ser otro tipo de barra como WoodenBar.

3

Aquí es su problema:

Bar B = CreateBar(); 
SteelB = B; 

B es un bar de cualquier tipo. Está intentando asignarlo a SteelBar. Eso está mal, podría ser una barra de cualquier tipo (cobre, madera, Tiki, ...). Usted puede hacer esto:

SteelBar sb = new SteelBar(); 
Bar b = sb; 

Debido a que un SteelBar es una barra de algún tipo, pero lo contrario no es cierto ..

Además, estoy seguro de que podría llamar SteelBar = CreateBar()

Estás seguro de algo que es falso. Intentalo; CreateBar devuelve una instancia de una barra de cualquier tipo, no un SteelBar.

1

Como se mencionó en pycruft, no se puede asignar un objeto de un tipo de línea a una variable de subtipo. No entiendo por qué agrega un SteelBar de todos modos, ya que también tiene una propiedad Material. Esto me parece redundante.

Para lograr lo que estás tratando de hacer, debes crear un nuevo método de fábrica que construya un SteelBar desde el principio. Puede devolverlo como Bar de todos modos. Esta sería una implementación del Factory Pattern.

Sin embargo, un poco más de información sobre lo que está tratando de lograr podría ayudar.

0

Seguramente esto sería más fácil de lograr con abstracciones como interfaces ... p. Ej. IMeasureable e IPhysical y no clases básicas ...

Usaría una BaseClass solo en la representación de la GUI para facilitar su visualización y obligaría a la clase base a implementar las interfaces requeridas.

Se podría utilizar también, opcionalmente, un DisplayObject que se sella y se lleva a un IMeasurable o IPhysical ...

1

que sigue diciendo que no puedo implícitamente crear una clase de más arriba a partir de una clase más abajo

El mejor ejemplo que uso para esto es Fruit y apple. La herencia es una relación "es-a".Un apple is-a Fruit sino un Fruitno es unapple, ya que puede ser un orange, banana ...

Volver a su ejemplo, un SteelBar es una Bar sino un Bar no es un SteelBar como pueda ser un WoodenBar y eso explica por qué no se puede echar la superclase de la clase hija

0

Considere este ejemplo:

public class Super { 
} 

public class Sub : Super { 
} 

Si crea el objeto Super no puede asignarlo como Sub porque no es un "Sub". La programación OO le permite "tratar con" objetos en términos de menos clases derivadas, pero este simple hecho aún permanece:

Ha creado un Super not a Sub.

La única forma de crear un Sub desde un Super sería crear un nuevo Sub y copiar los valores de las propiedades. Una herramienta como AutoMapper funciona bien para hacer esto rápidamente, de lo contrario terminará con un montón de líneas de código frágil mundano.