Quiero saber la razón detrás del diseño de la restricción de los Métodos Abstractos No Clase Abstracta (en C#).

Entiendo que la instancia de la clase no tendrán la definición y por lo tanto no se puede llamar, pero cuando los métodos estáticos son definidas,están excluidos de la instancia. ¿Por qué los métodos abstractos no se manejan de esa manera, ninguna razón específica para el mismo?

Que puede ser permitido en concreto de la clase y la clase derivada puede ser forzado a implementar métodos, básicamente, que es lo que se hace en el caso de los métodos abstractos en una clase abstracta.

  • Espero que no soy el único que dice.. «Wut?»
  • ¿Cuál es tu caso de uso donde desea definir un método abstracto en una clase no abstracta?
  • Por favor, añada un ejemplo de una clase en la que dicho concepto sería útil.
  • Tomar cualquier clase abstracta, por ejemplo, con un método abstracto y muchos métodos concretos. Si no tengo restricción, no puede esta clase abstracta ser eliminado y aún el mismo objetivo se logra?
  • Si usted tiene su corazón puesto en esto, tal vez usted puede considerar hacer el método virtual lugar y tiene a tiro un NotImplementedException (o no hacer nada, o devolver un valor predeterminado). A continuación, el documento que heredan las clases deben implementar el método. Pero en general, estoy de acuerdo con los demás; esto suena como usted está tratando de utilizar la herramienta equivocada para el trabajo.
  • Qué piensa usted de algo similar a un partial método en el que está bien llamar al método, incluso si no se «parte» de la clase (o estructura) proporciona una aplicación de la que partial método? El compilador simplemente quita («optimiza la distancia») la llamada a la partial método en ese caso. Es que lo que usted quiere que suceda si alguien es llamado el «resumen» de la versión del método, en su supuesta escenario?
  • Parcial es opcional (parcial de la clase/método puede tener otras partes definido o no), no estoy subrayando opcional de estado para los métodos abstractos, debería ser obligatorio para los niños de las clases.
  • Un caso que me acaba de topamos es la herencia de control de usuario para agregar un par de conocidos miembros de un control con varios super clases. Como esta clase en su propia es inútil, me hizo abstracto pero, a continuación, el diseñador de las superclases se negó a utilizar ya que no;t ser creado. Traté de hacer que los métodos abstractos (por lo que tiene que ser reemplazado) y se lanzó el error de compilación mencionado en el tema. He resuelto con un método virtual y tirar NotImplementedException con un mensaje adecuado.

InformationsquelleAutor Ashish Jain | 2012-09-25

8 Comentarios

  1. 44

    Primero, creo que lo que estamos pidiendo no es lógicamente sentido. Si usted tiene abstract método, que básicamente significa que el método que está sin terminar (como @ChrisSinclair señalado). Pero eso también significa que toda la clase está sin terminar, por lo que también tiene que ser abstract.

    U otra forma de decirlo: si había abstract método de una clase que no era abstract, eso significaría que había un método que no puede ser llamado. Pero eso significa que el método no es útil, se puede quitar y todos funcionan de la misma.

    Ahora, voy a tratar de ser más concreto por medio de un ejemplo: imaginemos el siguiente código:

    Animal[] zoo = new Animal[] { new Monkey(), new Fish(), new Animal() };
    
    foreach (Animal animal in zoo)
        animal.MakeSound();

    Aquí, Animal es la no-abstract de la clase base (que es la razón por la que me puede poner directamente en la matriz), Monkey y Fish se derivan de Animal y MakeSound() es el abstract método. Lo que debe este código? No estado que claramente, pero puedo imaginar que algunas opciones:

    1. Usted no puede llamar a MakeSound() en una variable de tipo Animal, se le puede llamar sólo mediante una variable de tipo como una de las clases derivadas, así que esto es un error de compilación.

      Esta no es una buena solución, porque el punto de abstract es ser capaz de tratar las instancias de clases derivadas de la clase base, y aún así obtener el comportamiento específico de la clase derivada. Si usted desea esto, sólo hay que poner una normal (no abstract, virtual o override) método en cada clase derivada y no hacer nada con la clase base.

    2. Usted no puede llamar a MakeSound() en un objeto cuyo tipo en tiempo de ejecución es en realidad Animal, así que esto es un error de tiempo de ejecución (una excepción).

      Esto no es también una buena solución. C# es un lenguaje de tipo estático y por lo que trata de atrapar a los errores como «no se puede llamar a este método» en tiempo de compilación (con obvias excepciones como la reflexión y dynamic), por lo que hacer esto en un error de tiempo de ejecución no encaja con el resto de la lengua. Además, usted puede hacer esto fácilmente mediante la creación de un virtual método en la clase base que lanza una excepción.

    Para resumir, usted quiere algo que no tiene mucho sentido, huele mal diseño (clase base que se comporta de manera diferente que sus clases derivadas) y puede ser solucionado fácilmente. Todos estos son signos de una característica que debe no ser implementado.

    • Sentido para mí y el punto 1 me da la respuesta de por qué no se resumen en «nivel de clase» y por qué las clases abstractas debe ser restringido de decisiones de las instancias. Gracias vick.
  2. 11

    Así pues, usted desea permitir

    class C { abstract void M(); }

    a compilar. Supongamos que lo hizo. ¿Qué desea que suceda cuando alguien hace

    new C().M();

    ? Quieres una ejecución error de tiempo? Bueno, en general C# prefiere errores en tiempo de compilación para la ejecución de los errores en tiempo. Si no te gusta que la filosofía, hay otros idiomas disponibles…

    • Me dijo que el problema y dado ejemplo de métodos estáticos siendo manejado por el compilador. Mi pregunta era sobre el compilador de diseño para los métodos abstractos, básicamente, por qué se eligió clase abstracta específicamente para estos métodos?
    • Porque un abstract clase no puede ser instanciado. Se trata de «inacabado», al igual que un interface no puede ser instanciado porque lo que el vacío métodos/propiedades hacer es indefinido. Obliga a los programadores que deseen hacer uso de ellos para heredar y aplicar todo los métodos abstractos antes de ser capaz de crear una instancia. EDIT: métodos Estáticos son una diferentes concepto. Pertenecen a la Tipo y no la instancia del objeto. Los métodos abstractos son en el ejemplo nivel y que requieren para ser implementado (también tenga en cuenta que los métodos estáticos requieren ser implementadas — no «abstracto estática» existe)
    • Si desea que la ejecución error de tiempo, puede hacer que ya: crear un método virtual que lanza una excepción.
    • Los métodos estáticos son un caso diferente, ya que no están en una instancia en cualquier caso. No sé a qué te refieres con «por qué eligieron clase abstracta específicamente para estos métodos?». He mostrado el potencial problema de si una clase concreta se les permitió tener métodos abstractos. ¿Qué preferiría que pasó?
    • Aún más divertido si el método abstracto había un tipo de retorno en lugar de vacío. 🙂 Al menos un método void puede hacer nada, pero ¿qué hace un tipo de retorno de hacer? default valor? Sí, yo no sé qué otra cosa iba a suceder. Abstracto está ahí por una razón, nada puede ser manejado por virtual como lo hemos sugerido.
    • He estado esta manera: planteamiento del Problema era proporcionar método abstracto de la funcionalidad (si hubo alguna otra intención, entonces su fina para ofrecer un nuevo concepto de «clase abstracta»). Ahora este problema podría ser resuelto por el compilador de los diseñadores de «n» maneras (estoy llamando como «n» porque no podía ser de otra manera), uno de ellos es la implementación actual. Yo soy de razonamiento en forma alternativa la adopción, por qué JAVA/C# (puede ser más idiomas) adoptado para proporcionar un adicional de tipo «resumen a nivel de clase, es decir, las clases abstractas» y no eligió a manejar a nivel de método?
    • Aún no se ha propuesto que manejar a nivel de método’ podrían, en realidad, media. ¿Qué desea que suceda, en la situación anterior?
    • Lo que significa que no existe el concepto de «clase abstracta», más bien sería la palabra clave abstract aplicables a los métodos/propiedades/indizadores etc solo. Y para proporcionar un tipo de modelo no es de la interfaz. Estoy seguro de que habría una razón «virtual» no es aplicable a nivel de clase, mientras que el «resumen» es.

  3. 4

    Creo que he respondido a tu propia pregunta, un método abstracto no está definido inicialmente. Por lo tanto, la clase no puede ser instanciated. Estás diciendo que debería ignorar, pero, por definición, cuando la adición de un método abstracto que estás diciendo «cada una de las clases creadas a partir de esta debe implementar este {método abstracto}» por lo tanto la clase donde se define la clase abstracta debe también ser abstracta debido a que el método abstracto es aún indefinido en ese punto.

  4. 1

    Usted puede lograr lo que desee, utilizando «virtual» métodos, pero el uso de virtual métodos puede llevar a más de tiempo de ejecución de la lógica de negocio de los errores como desarrollar no está «obligado» a aplicar la lógica en el niño de la clase.

    Creo que hay un punto válido aquí. Un método abstracto es la solución perfecta, ya que se tendría que «hacer cumplir» la exigencia de definir el método cuerpo en los niños.

    Me he encontrado con muchas situaciones en las que la clase padre había (o sería más eficiente a) aplicar un poco de lógica, pero «Sólo» los niños pueden implementar resto de la lógica»

    Así que si la oportunidad se no me gusto la mezcla de métodos abstractos con completa métodos.

    @AakashM, aprecio C# prefiere errores de tiempo de compilación. Yo Y así lo hace nadie. Esto es pensar fuera de la caja.

    Y apoyo esto no va a afectar eso.

    Vamos a pensar fuera de la caja aquí, en lugar de decir «viva» para big boy decisiones.

    Compilador de C# puede detectar y rechazar a alguien de uso de una clase abstracta directamente porque utiliza la palabra clave «abstract».

    C# también se sabe que la fuerza de cualquier niño de la clase para implementar cualquier método abstracto. Cómo? debido a la utilización de la palabra clave «abstract».

    Esto es bastante sencillo de entender para cualquiera que haya estudiado el funcionamiento interno de un lenguaje de programación.

    Así que, ¿por qué no puede C# detectar un «resumen» de palabras clave junto a un método en una clase normal y manejar en el TIEMPO de COMPILACIÓN.

    La razón es que se requiere «reelaboración» y el esfuerzo no vale la pena apoyar a la pequeña de la demanda.

    Especialmente en un sector que carece de gente que piensa de las cajas que los niños grandes que les han dado.

  5. 1

    La clase abstracta puede contener miembro abstracto. No es la única declaración de método si cualquier método tiene un resumen de palabras clave que no podemos implementar en la misma clase. Así que la clase abstracta es incompleto. Es por eso que el objeto no está creado para una clase abstracta.

    Clase no abstracta no puede contener miembro abstracto.

    Ejemplo:

    namespace InterviewPreparation
    {
       public abstract class baseclass
        {
            public abstract void method1(); //abstract method
            public abstract void method2(); //abstract method
            public void method3() { }  //Non- abstract method----->It is necessary to implement here.
        }
        class childclass : baseclass
        {
            public override void method1() { }
            public override void method2() { }
        }
        public class Program    //Non Abstract Class
        {
            public static void Main()
            {
                baseclass b = new childclass(); //create instance
                b.method1();
                b.method2();
                b.method3();
            }
        }
    
    }
  6. 0

    Aún no está claro por qué se quiere que, pero un enfoque alternativo podría ser la fuerza de las clases derivadas para proporcionar una instancia de delegado. Algo como esto

    class MyConcreteClass
    {
      readonly Func<int, DateTime, string> methodImpl;
    
      //constructor requires a delegate instance
      public MyConcreteClass(Func<int, DateTime, string> methodImpl)
      {
        if (methodImpl == null)
          throw new ArgumentNullException();
    
        this.methodImpl = methodImpl;
      }
    
      ...
    }

    (La firma string MethodImpl(int, DateTime) es sólo un ejemplo, por supuesto).

    De lo contrario, puedo recomendar las otras respuestas para explicar por qué su deseo, probablemente, no es algo que haría que el mundo sea mejor.

    • Su fina para aceptar que las alternativas no son mejores o incluso tener graves inconvenientes. Pero, ¿por qué la implementación actual de clases abstractas (¿por qué no mantener resumen de los métodos/propiedades/indizadores etc como virtual) es el mejor y fue el concepto de «clases abstractas» inevitable (debido a sus ventajas sobre otras formas), teniendo en cuenta las interfaces ya están allí?
  7. 0

    Por lo que las respuestas anteriores son correctas: tener métodos abstractos que hace la clase inherentemente abstracto. Si usted no puede instancia de parte de una clase, entonces usted no puede instancia de la misma clase. Sin embargo, las respuestas de arriba en realidad no discutir sus opciones aquí.

    Primera, esto es principalmente un problema para público métodos estáticos. Si los métodos no están destinados a ser público, entonces usted podría haber protegido no-métodos abstractos, los cuales son permitidos en una clase abstracta de la declaración. Así, sólo podía mover estos métodos estáticos a una clase estática sin mucho problema.

    Como alternativa, se podría mantener estos métodos en la clase, pero, a continuación, en lugar de tener métodos abstractos, declarar una interfaz. Esencialmente, usted tiene múltiples herencia problema como usted desea de la clase derivada hereda de dos conceptualmente diferentes objetos: un no-resumen de los padres con los miembros static públicos, y un resumen de los padres con los métodos abstractos. A diferencia de otros marcos, C# permite la herencia múltiple. En su lugar, C# ofrece una interfaz formal declaración de que es la intención de llenar este propósito. Por otra parte, el punto de métodos abstractos que, en realidad, es sólo para imponer una cierta conceptual de la interfaz.

  8. -1

    Tengo un escenario muy similar a lo que el OP está tratando de lograr. En mi caso el método que yo quiero hacer resumen sería un protegido método y sólo se sabe que la clase base. Así que el «new C().M();» no se aplica debido a que el método en cuestión no es pública. Quiero ser capaz de crear y llamar a los métodos públicos de la clase base (por eso es necesario no abstracta), pero necesito estos métodos públicos para llamar a un protegido aplicación del método protegido en el niño de la clase y no tienen ningún defecto de la aplicación en el padre. En una forma de hablar, necesito la fuerza de los descendientes de sustituir el método. No sé lo que el niño de clase es en tiempo de compilación debido a la inyección de dependencias.

    Mi solución fue seguir las reglas y el uso de una base de hormigón de la clase y una virtual protegido método. Para la implementación predeterminada, sin embargo, voy a lanzar una NotImplementedException con el error «La aplicación de nombre de método debe ser proporcionada en la implementación de la clase hija.»

    protected virtual void MyProtectedMethod() 
    { 
      throw new NotImplementedException("The implementation for MyProtectedMethod must be provided in the implementation of the child class."); 
    }

    De esta manera una implementación predeterminada nunca pueden ser usadas y los ejecutores de los descendientes de las implementaciones verá rápidamente que les falta un paso importante.

    • Para sustituir un error del compilador, con una excepción en tiempo de ejecución? Si la clase no es abstracto que el riesgo en un momento u otro que no esta implementado el método se llama en una instancia de la clase y se lanza una excepción. Si te refieres resumen, a continuación, utilice simplemente abstracto y no trate de trabajar alrededor de ella.
    • Un error de tiempo de ejecución es un razonable equilibrio dado que el marco de/lenguaje da para ningún otro mecanismo para lograr lo que el OP está pidiendo. En mi caso, estoy seguro de que si le pego el error de tiempo de ejecución, lo voy a encontrar muy temprano en el proceso de desarrollo. El niño de clase no se utiliza o se utiliza todo el tiempo (núcleo de utilidad). Sólo estoy ofreciendo una alternativa de solución a la necesidad de definir un método en una clase concreta que se requiere para ser reemplazado en cualquier niño de la clase.
    • Ed no es claro para mí cómo mi post no es abordar directamente la cuestión en el OP ofreciendo una solución a la limitación del marco/idioma??? Por favor, póngase en contacto conmigo directamente si usted siente mi post es tan inapropiado.

Dejar respuesta

Please enter your comment!
Please enter your name here