usar una sirve sellada que protegido para nuevo miembro metodos metodo español ejemplos declarado clases clase caracteristicas abstractas abstracta c# oop compiler-construction

una - sealed class c# español



Método abstracto en clase no abstracta (8)

Creo que has respondido tu propia pregunta, un método abstracto no está definido inicialmente. Por lo tanto, la clase no puede ser instanciada. Estás diciendo que debería ignorarlo, pero por definición al agregar un método abstracto estás diciendo que "cada clase creada a partir de esto debe implementar este {método abstracto}", por lo tanto, la clase donde defines la clase abstracta también debe ser abstracta porque el el método abstracto aún no está definido en ese punto.

Quiero saber el motivo detrás del diseño de restringir los métodos abstractos en la clase no abstracta (en C #).

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

Podrían permitirse en una clase concreta y la clase derivada puede verse obligada a implementar métodos, básicamente eso es lo que se hace en el caso de los métodos abstractos en una clase abstracta.


Entonces, las respuestas anteriores son correctas: tener métodos abstractos hace que la clase sea inherentemente abstracta. Si no puede instanciar parte de una clase, entonces no puede instanciar la clase en sí misma. Sin embargo, las respuestas anteriores realmente no discutieron sus opciones aquí.

En primer lugar, esto es principalmente un problema para los métodos públicos estáticos. Si los métodos no están destinados a ser públicos, entonces podría haber protegido métodos no abstractos, que están permitidos en una declaración de clase abstracta. Por lo tanto, podría simplemente mover estos métodos estáticos a una clase estática separada sin mucho problema.

Como alternativa, puede mantener esos métodos en la clase, pero luego, en lugar de tener métodos abstractos, declare una interfaz. Básicamente, tiene un problema de herencia múltiple porque desea que la clase derivada herede de dos objetos conceptualmente diferentes: un elemento primario no abstracto con miembros estáticos públicos y un elemento primario abstracto con métodos abstractos. A diferencia de algunos otros marcos, C # permite herencia múltiple. En cambio, C # ofrece una declaración de interfaz formal que está destinada a cumplir este propósito. Además, el objetivo de los métodos abstractos, en realidad, es simplemente imponer una cierta interfaz conceptual.


Entonces, quieres permitir

class C { abstract void M(); }

compilar. Supongamos que sí. ¿Qué quieres que suceda cuando alguien lo hace?

new C().M();

? ¿Quieres un error de tiempo de ejecución? Bueno, en general, C # prefiere los errores de tiempo de compilación a los errores de tiempo de ejecución. Si no te gusta esa filosofía, hay otros idiomas disponibles ...


La clase abstracta puede contener un miembro abstracto. Existe la única declaración de método si un método tiene una palabra clave abstracta que no podemos implementar en la misma clase. Entonces la clase abstracta está incompleta. Es por eso que el objeto no se crea para una clase abstracta.

La clase no abstracta no puede contener miembros abstractos.

Ejemplo:

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


Primero, creo que lo que estás preguntando no tiene lógicamente sentido. Si tienes un método abstract , básicamente significa que el método está inacabado (como señaló @ChrisSinclair). Pero eso también significa que toda la clase está inacabada, por lo que también tiene que ser abstract .

O bien, otra forma de decirlo: si tuvieras abstract método abstract en una clase que no fuera abstract , eso significaría que tienes un método que no se puede invocar. Pero eso significa que el método no es útil, podrías eliminarlo y todo funcionaría igual.

Ahora, intentaré ser más concreto usando un ejemplo: imagine 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 clase base no abstract (por lo que puedo ponerlo directamente en la matriz), Monkey y Fish se derivan de Animal y MakeSound() es el método abstract . ¿Qué debería hacer este código? No lo dijiste claramente, pero puedo imaginar algunas opciones:

  1. No puede llamar a MakeSound() en una variable escrita como Animal , puede llamarla solo utilizando una variable escrita como una de las clases derivadas, por lo que este es un error de compilación.

    Esta no es una buena solución, porque el objetivo del abstract es poder tratar instancias de clases derivadas como la clase base, y aún obtener un comportamiento que sea específico de la clase derivada. Si quiere esto, simplemente coloque un método normal (no abstract , virtual o de override ) en cada clase derivada y no haga nada con la clase base.

  2. No puede llamar a MakeSound() en un objeto cuyo tipo de tiempo de ejecución es Animal , por lo que este es un error de tiempo de ejecución (una excepción).

    Esta tampoco es una buena solución. C # es un lenguaje estáticamente estático y trata de detectar errores como "no se puede llamar a este método" en tiempo de compilación (con excepciones obvias como reflejo y dynamic ), por lo que convertir esto en un error de tiempo de ejecución no encajaría con el resto del lenguaje Además, puede hacerlo fácilmente creando un método virtual en la clase base que arroje una excepción.

En resumen, quiere algo que no tiene mucho sentido, huele mal al diseño (clase base que se comporta de manera diferente a sus clases derivadas) y puede solucionarse con bastante facilidad. Todos estos son cantados de una característica que no debería ser implementada.


Puede lograr lo que quiera utilizando métodos "virtuales", pero el uso de métodos virtuales puede generar más errores de lógica de negocio en tiempo de ejecución, ya que desarrollar no es "forzoso" para implementar la lógica en la clase secundaria.

Creo que hay un punto válido aquí. Un método abstracto es la solución perfecta ya que "impondría" el requisito de definir el cuerpo del método en los niños.

He encontrado muchas situaciones en las que la clase de padres tenía que (o sería más eficiente) implementar cierta lógica, pero "solo" los niños podían implementar el resto de la lógica "

Entonces, si existiera la oportunidad, felizmente mezclaría métodos abstractos con métodos completos.

@AakashM, aprecio que C # prefiera los errores de tiempo de compilación. Yo también. Y también cualquiera. Se trata de pensar fuera de la caja.

Y apoyar esto no afectará eso.

Pensemos fuera de la caja aquí, en lugar de decir "hurrah" a las decisiones de los muchachos.

El compilador de C # puede detectar y negar a alguien el uso de una clase abstracta directamente porque usa la palabra clave "abstracta".

C # también sabe forzar a cualquier clase infantil a implementar cualquier método abstracto. ¿Cómo? debido al uso de la palabra clave "abstracta".

Esto es bastante simple de entender para cualquiera que haya estudiado los aspectos internos de un lenguaje de programación.

Entonces, ¿por qué C # no puede detectar una palabra clave "abstracta" al lado de un método en una clase normal y manejarla en el TIEMPO DE COMPILACIÓN?

La razón es que se necesita "reelaboración" y el esfuerzo no vale la pena apoyar la pequeña demanda.

Especialmente en una industria que carece de personas que piensan en las cajas que los niños grandes les han dado.


Tengo un escenario muy similar a lo que el PO intenta lograr. En mi caso, el método que quiero hacer abstracto sería un método protegido y solo sería conocido por la clase base. Entonces el "nuevo C (). M ();" no se aplica porque el método en cuestión no es público. Quiero poder instanciar y llamar a los métodos públicos en la clase base (por lo tanto, no debe ser abstracto), pero necesito estos métodos públicos para llamar a una implementación protegida del método protegido en la clase secundaria y no tener implementación predeterminada en el padre En cierto modo, necesito forzar a los descendientes a que anulen el método. No sé cuál es la clase secundaria en el momento de la compilación debido a la inyección de dependencia.

Mi solución fue seguir las reglas y usar una clase base concreta y un método protegido virtual. Sin embargo, para la implementación predeterminada lanzo una NotImplementedException con el error "La implementación del nombre del método debe proporcionarse en la implementación de la clase secundaria".

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

De esta forma, nunca se puede usar una implementación predeterminada y los implementadores de las implementaciones descendentes verán rápidamente que perdieron un paso importante.


Todavía no está claro por qué querría eso, pero un enfoque alternativo podría ser forzar a las clases derivadas a 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 string MethodImpl(int, DateTime) firma string MethodImpl(int, DateTime) es solo un ejemplo, por supuesto).

De lo contrario, puedo recomendar las otras respuestas para explicar por qué tu deseo probablemente no sea algo que mejore el mundo.