what new method example and c# virtual private

new - virtual class c# example



¿Por qué los métodos virtuales privados son ilegales en C#? (6)

Déjenme aclarar esto: C # no es C ++.

C # se diseña varias décadas después de C ++ y se construye utilizando ideas avanzadas a lo largo de los años. En mi humilde opinión C # está bien definido y finalmente maneja la orientación del objeto de la manera correcta (imho). Incluye la declaración internal por una razón y no le permite "virtualizar" y anular los métodos privados. Por una razón.

Todos los problemas descritos anteriormente (las clases internas que reemplazan a private virtual métodos private virtual , que usan el patrón abstracto de fábrica de esta manera, etc.) se pueden escribir fácilmente de una manera diferente utilizando las interfaces y el enunciado internal . Una vez dicho esto, debo decir que es una cuestión de gusto si le gusta el modo C ++ o el modo C #.

Prefiero usar un código descriptivo (código que habla por sí mismo, sin usar comentarios) y uso interfaces en lugar de una herencia profunda. Sobrescribir los métodos virtuales privados me parece piratería informática o spaghetti, independientemente de si es una práctica común, un patrón de uso frecuente o hace el trabajo.

He estado desarrollando en C ++ durante casi 1,5 décadas y nunca encontré la necesidad de primar métodos privados ... (Puedo ver los comentarios volando en :-))

Viniendo de un fondo C ++, esto fue una sorpresa para mí. En C ++ es una buena práctica hacer que las funciones virtuales sean privadas. De http://www.gotw.ca/publications/mill18.htm : "Pauta n.º 2: Prefiere hacer que las funciones virtuales sean privadas".

También cito el blog de Eric Lippert, de Knights-knaves-protected-and-internal :

Los métodos virtuales privados son ilegales en C #, lo que me molesta muchísimo. Usaría totalmente esa característica si la tuviéramos.

Entiendo que en C #, no podría sobrescribir un método virtual privado en una clase derivada (pero no anidada). ¿Por qué es este el caso? En C ++, el especificador de acceso no tiene nada que ver con si puede anular una función o no.


Debido a que los métodos privados SOLO se puede acceder desde la clase que los define, por lo tanto, un método virtual privado sería inútil. Lo que quieres es un método virtual protegido. La clase que lo define y cualquier subclase puede acceder a un método protegido.

EDITAR:

Al proporcionar palabras clave privadas y protegidas C # le permite un control más detallado de sus métodos. Eso es privado significa completamente cerrado y protegido significa completamente cerrado aparte de las subclases. Esto le permite tener métodos que solo su superclase conoce y métodos que las subclases pueden conocer.


En C # (y en la CLI, por lo que he visto), "privado" tiene un significado bastante claro e inequívoco: "accesible solo en esta clase". El concepto de los virtuales privados atormenta a todos, sin mencionar que los espacios de nombres son un poco campo de minas. ¿Por qué debería tener que importarme lo que llamaste un método que ni siquiera puedo ver, y recibir una advertencia del compilador por haber elegido un nombre que ya te enganchó?


Observo que hay dos preguntas aquí. En el futuro, podría considerar publicar dos preguntas en lugar de combinar dos preguntas en una. Cuando combina preguntas como esta, a menudo lo que sucede es que solo el primero recibe una respuesta.

La primera pregunta es "¿por qué los métodos virtuales privados son ilegales en C #?"

Aquí están los argumentos en contra de la característica de "métodos virtuales privados":

  1. privado virtual solo es útil cuando tiene una clase derivada anidada. Este es un patrón útil, pero mucho menos común que la situación de clase derivada no anidada.

  2. Si desea restringir la capacidad de anular el método en clases derivadas no anidadas, puede hacerlo restringiendo la capacidad de las clases no anidadas para derivar de la clase base; hacer que todos los constructores de la clase base sean privados. Por lo tanto, no es necesario tener privacidad virtual para evitar la anulación; protected virtual es suficiente, porque las únicas clases derivadas se anidarán.

  3. Si desea restringir la capacidad de llamar a un método en una clase derivada no anidada, puede hacer que el método sea interno virtual y luego decirle a sus compañeros de trabajo que no utilicen ese método. Es irritante no hacer cumplir esto por el compilador, pero el compilador no impone ninguna otra restricción semántica sobre cómo se supone que debe usarse un método; obtener la semántica correcta es su negocio, no el del compilador, y debe aplicarlo con las revisiones de código adecuadas. Por lo tanto, lo privado virtual no es necesario para evitar llamadas; revisiones internas virtuales de código plus son suficientes.

  4. Es posible implementar este patrón ya con partes existentes:

    abstract class C { private int CF() { whatever; } private Func<int> f; public C() { f = CF; } private int F() { return f(); } private class D : C { private int DF() { whatever; } public D() { f = DF; } }

    Ahora tengo un método F que es efectivamente virtual, pero solo puede ser "anulado" por clases anidadas derivadas.

Dado que en todos los casos, tanto el interno protegido como el interno hacen el truco, el privado virtual es innecesario. Casi nunca es lo correcto, ya que debe estar comprometido con el uso del patrón de clase derivado anidado. Entonces, el lenguaje lo hace ilegal.

Los argumentos para son:

Ha habido ocasiones en el código real cuando deseo que un método virtual sea un detalle de implementación privada de una clase que deseo que se amplíe tanto por clases internas anidadas como por clases internas anidadas. Tener que hacer cumplir la invariante que el método interno no es llamado por mis compañeros de trabajo es irritante; Me gustaría que el compilador haga cumplir esto sin que yo tenga que saltar por los aros locos como crear un campo de tipo delegado, etc.

Además, simplemente está la cuestión de la consistencia y la ortogonalidad. Parece extraño que dos cosas que deberían ser independientes -accesibilidad y virtualidad- tengan un efecto mutuo innecesario.

Los argumentos en contra de la característica son bastante fuertes. Los argumentos para son bastante débiles. Por lo tanto, no hay tal característica. Personalmente me gustaría mucho, pero entiendo totalmente por qué el equipo de diseño nunca me ha aceptado. No vale la pena el costo, y no me gustaría enviar una característica mejor porque gastamos el presupuesto en una función que no beneficia a casi nadie.

La segunda pregunta es "¿Por qué en C # no puede sobrescribir un método virtual privado en una clase derivada no anidada?"

Hay varias razones.

  1. Porque solo puedes anular lo que puedes ver. Un método privado es un detalle de implementación privada de una clase base y no debe ser accesible.

  2. Porque permitir eso tiene serias implicaciones de seguridad. Recuerde, en C ++ casi siempre compila código en una aplicación a la vez. Usted tiene el código fuente para todo; todo es esencialmente "interno" desde la perspectiva de C ++ la mayor parte del tiempo. En C #, ese no es el caso en absoluto. Las asambleas de terceros pueden acceder fácilmente a los tipos públicos de las bibliotecas y producir nuevas extensiones para esas clases, que luego se pueden usar a la perfección en lugar de las instancias de la clase base. Como los métodos virtuales cambian efectivamente el comportamiento de una clase, cualquier código que dependa por razones de seguridad de las invariantes de esa clase debe diseñarse cuidadosamente para que no dependan de invariantes garantizados por la clase base. Restringir el acceso a los métodos virtuales ayuda a garantizar que se mantengan las invariantes de esos métodos.

  3. Porque permitir eso proporciona otra forma del problema de la clase base frágil. C # ha sido cuidadosamente diseñado para ser menos susceptible al problema de clase de base frágil que otros lenguajes de OO. Si un método virtual inaccesible puede ser anulado en una clase derivada, ese detalle de implementación privada de la clase base se convierte en un cambio radical si se altera. Los proveedores de clases base deberían poder cambiar sus detalles internos sin preocuparse demasiado por el hecho de que hayan roto las clases derivadas que dependen de ellos; lo ideal es que solo se mantenga la interfaz pública y documentada para un tipo cuando cambien los detalles de la implementación.


Porque C # no tiene ningún mecanismo para proporcionar herencia pública / privada / protegida, que es lo que realmente buscas.

Incluso en C ++, las clases derivadas no pueden acceder a los miembros privados, pero pueden limitar la visibilidad de la clase base al especificar la visibilidad de la herencia:

class Derived : /*->>*/private/*<--*/ Base { }

C # proporciona un montón de otras cosas para que pueda controlar la visibilidad de los miembros de su clase. Entre protected e internal , debe poder obtener la jerarquía exactamente como lo desee.

En mi humilde opinión C # impone una relación IS-A más fuerte a través de la herencia de una única clase base, por lo que tiene sentido que si un auto tiene un motor, una subclase BMW no debería ser capaz de ocultarlo.

C ++ admite la herencia múltiple, que es una relación IS-A menos estricta; es casi como una relación HAS-A en la que puede incorporar múltiples clases no relacionadas. Debido a la capacidad de incorporar múltiples clases base, desea un control más estricto sobre la visibilidad de todas ellas.


Supongo que la razón es que internal virtual hace casi lo mismo que el private virtual y es algo menos confuso para aquellos que no están familiarizados con el idioma private virtual .

Mientras que solo las clases internas pueden anular private virtual métodos private virtual , solo classess en su conjunto puede anular internal virtual métodos internal virtual .