virtuales sobreescrito poo new must modificador metodos metodo example c# inheritance language-features inheritance-prevention

sobreescrito - public void override c#



¿Cómo ocultar(eliminar) los métodos de una clase base en C#? (10)

C # no tiene un concepto similar a la herencia privada o protegida en C ++.

Su mejor opción es agregar una instancia de la clase y exponer el conjunto de métodos que le interesan a los que tienen acceso los consumidores.

Aunque en su caso no creo que sea posible, podría buscar crear una interfaz que exponga solo la funcionalidad común con la que desea que los consumidores trabajen, de modo que su contenedor pueda ser sustituible en algunos casos por su agregado.

La esencia del problema es dada una jerarquía de clases como esta:

class A { protected void MethodToExpose() {} protected void MethodToHide(object param) {} } class B : A { new private void MethodToHide(object param) {} protected void NewMethodInB() {} } class C : B { public void DoSomething() { base.MethodToHide("the parameter"); // This still calls A.MethodToHide() base.MethodToExpose(); // This calls A.MethodToExpose(), but that''s ok base.NewMethodInB(); } }

¿Cómo puedo evitar que las clases heredadas de la clase "B" vean el método A.MethodToHide() ? En C ++, esto fue bastante fácil al usar una declaración como la class B : private A , pero esta sintaxis no es válida en C #.

Para aquellos interesados ​​(o preguntándose qué estoy tratando de hacer), lo que estamos tratando de hacer es crear un contenedor para Rhino.Commons.NHRepository que oculte los métodos que no queremos exponer a nuestro grupo de desarrolladores , por lo que podemos tener una forma única de desarrollar nuestra aplicación que los nuevos desarrolladores puedan seguir fácilmente. Entonces, sí, creo que la prueba "Is-A" es válida para toda la cadena (WidgetRepository Is-A BaseRepository Is-A NHRepository).

Editar : Debería haber mencionado, por el bien de la discusión, que la clase A es una clase API fuera de nuestro control. De lo contrario, el problema se vuelve considerablemente más fácil.


No puedes hacerlo y preservar la jerarquía. Si es posible, debe crear interfaces que definan su ideal, luego subclasifique las clases base e implemente las interfaces. Haga referencia solo a las interfaces (no a los tipos de clases base) en su código.

El patrón de Adaptador fue creado específicamente para resolver el problema de cómo usar un marco cuando su API no se alinea exactamente con sus necesidades.


Nunca supe que podrías hacer eso en C ++, aunque no sé mucho sobre C ++. Me temo que estoy de acuerdo con Blixt en que una clase de envoltura es probablemente la forma en que implementaría esto.

Podría funcionar (pero no estoy seguro) simplemente anular la función y lanzar una excepción en una llamada ....


Por lo que sé, no puedes esconderlo de la manera que quieras. Creo que podrías evitar que se use de alguna manera práctica:

class B : A { public new void MethodToHide(object param) { throw new DontUseThisMethodException(); } protected void NewMethodInB() {} }

No es lo mejor que puedes hacer, por lo que probablemente quieras resolverlo de otra manera ...


Si desea personalizar un conjunto de características, diría que desea crear un contenedor en lugar de heredar la funcionalidad. No sé de una manera de hacer lo que quieras en C # tampoco.

Piénselo, ¿qué pasa si algún código fuera de su control quiere esta instancia de NHRepository para algo ... pero ha eliminado la funcionalidad de la función que necesita en su clase secundaria (que enviaría, ya que esa es su única instancia de NHRepository . ) Todo se dispara. Es por eso que no creo que sea posible prescindir de un feo truco.


Si está usando Visual Studio, puede ocultar los métodos / propiedades de intelliprompt con este atributo:

class A { protected void MethodToExpose() {} [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)] protected void MethodToHide(object param) {} }

En realidad, no se deshará de la función, pero si son solo tu gente interna. Puede ser lo suficientemente cerca.


Su código en la clase derivada B no ocultará el método base de todos los tipos derivados, solo él mismo. Debería establecer el método en privado en la base. La única forma de evitar este problema es crear otra clase base que no exponga este método.


En realidad, PUEDES ocultar el método de A desde C si hubieras definido el método de B como accesible desde C.

El único problema con su código es que usa "privado" en su declaración de ocultación ... si usa protegido o público no tendría ningún problema y funcionaría como esperaba. Lo hago todo el tiempo con los campos.


En mi opinión, la mejor manera de hacerlo, si solo quiere ocultar y no anular y externalizar una función nueva, es solo agregar un atributo EditorBrowsableState. Oculta el método en el editor visual studio. Quien intente usarlo terminará con un error de tiempo de compilación.

Simplemente agregue este código sobre su método:

[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]

Por ejemplo

public class User { public void DoSomething() { Something... } } public class Manager { [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)] public override void DoSomething() { } } void main() { User user = new User(); user.DoSomething(); Manager manager = new Manager(); manager.DoSomething(); // --------- This row will throw a design time error }

Buena suerte :)


Obsoleto

En la clase B, anule MethodToHide y agregue el atributo obsoleto

[Obsolete("Reason", true)] // true will cause a compile-time error

Establecer EditorBrowsable

(Como se mencionó previamente)

En la clase B, anule MethodToHide y agregue el atributo EditorBrowsable

[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]

Lanzar excepción

(Como se mencionó previamente)

En la clase B, reemplaza MethodToHide y lanza una excepción.

Crear Wrapper

Creo que Michael Meadows tiene razón. Use el patrón de adaptador . Este patrón también permite una burla más fácil del código cuando se realizan pruebas unitarias.

class B: IInterface { protected void MethodToExpose() { A a = new A(); a.MethodToExpose(); } protected void NewMethodInB() { } }