2010-04-30 11 views
8

Aquí está mi situación:¿Por qué se llama a la clase base?

interface Icontainer{ 
string name(); 
} 

abstract class fuzzyContainer : Icontainer{ 
    string name(){ 
    return "Fuzzy Container"; 
    } 
} 

class specialContainer: fuzzyContainer{ 
    string name(){ 
    return base.name() + " Special Container"; 
    } 
} 


Icontainer cont = new SpecialContainer(); 
cont.name(); // I expected "Fuzzy Container Special Container" as the output. 

Cuando ejecuto mi código como se describió anteriormente la salida es simplemente "Contenedor Difusa". que me estoy perdiendo aqui? ¿Hay una mejor manera de obtener los resultados deseados?

+1

este código no se compila como es .. y todavía ni siquiera después de que cambie la nueva SpecialContainer a specialContainer. –

+0

no se supone que debe ser un código sintácticamente correcto, solo ejemplo de código – IaCoder

Respuesta

17

Si hace nombre() virtual y luego override en specialContainer, obtendrá el comportamiento esperado.

public interface Icontainer 
{ 
    string name(); 
} 

public abstract class fuzzyContainer : Icontainer 
{ 
    public virtual string name() 
    { 
     return "Fuzzy Container"; 
    } 
} 

public class specialContainer : fuzzyContainer 
{ 
    public override string name() 
    { 
     return base.name() + " Special Container"; 
    } 
} 
3

Esto se debe a que está ocultando el método y no lo está anulando. Sin hacer que el método base sea virtual, no es posible anularlo, pero puede "ocultarlo" creando un método del mismo nombre.

Si tuviera:

SpecialContainer cont = new SpecialContainer(); 
cont.name(); 

Entonces también obtener la salida que esperaba.

La respuesta de Matt también funciona y puede ser preferible si puede editar la clase base para hacer que el método sea virtual. Por defecto, los métodos no son reemplazables a menos que estén explícitamente marcados como tales con la palabra clave virtual

0

El método 'nombre' en esa clase no reemplaza el método de nombre de fuzzyContainer. Por lo tanto, cuando se lanza el objetoContainer especial como un IContainer, solo tiene el método de nombre de la clase base para invocar.

3

Debe declarar el nombre-método virtual y anularlo en la clase derivada.

También me tomé la libertad de "arreglar" su código con las convenciones de nomenclatura más comunes.

abstract class FuzzyContainer : IContainer{ 
    protected virtual string GetName(){ 
    return "Fuzzy Container"; 
    } 
} 

class SpecialContainer: FuzzyContainer{ 
    override string GetName(){ 
    return base.GetName() + " Special Container"; 
    } 
} 
6

En primer lugar, es útil cuando tiene preguntas que publica el código que realmente compila. Es difícil analizar un problema cuando está lleno de modificadores y errores ortográficos faltantes; es difícil saber si el problema es un error tipográfico o no.

Una vez que hagamos el trabajo para arreglar el programa de modo que en realidad compila, el compilador emite una advertencia que le indica que la sobrecarga se ve mal. Ya que su pregunta es "¿por qué está sobrecargando la información?" probablemente sería una buena idea leer la advertencia del compilador que emitimos con precisión para que pueda analizar este problema.

El problema es que la clase derivada contiene un nuevo método llamado "nombre", no un override del método existente. Eso es lo que la advertencia intenta decirte.

Existen dos maneras de solucionar este problema, dependiendo de si se intentó el método para ser "nuevo" o "anular". Si pretendía que el método fuera "anulado", haga virtual la implementación base y anule la implementación derivada.

Si usted pretende que el método es "nuevo" y todavía desea que el nuevo método para reemplazar la unión a la implementación de la interfaz a continuación, utilizar interfaz reimplementación:

class SpecialContainer: FuzzyContainer, IContainer 
{ 
    public new string Name() 
    { 
    return base.Name() + " Special Container"; 
    } 
} 

Aviso el "nuevo" y el hecho de que tenemos re-afirmó que esta clase implementa IContainer. Esto le dice al compilador de "no tener en cuenta los enlaces a los métodos de IContainer deducidas de la clase base y empezar de nuevo."

+0

¿Hay situaciones verdaderamente convincentes que se necesita usar 'new'? La única vez que encuentre estoy usando 'new' es cuando estoy tratando de forzar un diseño que no debería ser. –

+4

@ Matt: IEnumerable se extiende IEnumerable. Ambos tienen un método llamado GetEnumerator que no toma argumentos. Tienes tres opciones. (1) no haga que el tipo de versión genérica sea compatible con la versión no genérica; romper la relación de extensión. (2) proponga un nombre diferente para GetEnumerator en la interfaz derivada. O (3) haga que el GetEnumerator de la versión derivada sea un "nuevo" método. ¿Cuál crees que es la peor de estas tres malas elecciones? Yo iría por (3). –

Cuestiones relacionadas