Pregunta

Si tiene varias clases donde desea que hereden de una clase base para una funcionalidad común, ¿debería implementar la clase base usando una clase o una clase abstracta?

¿Fue útil?

Solución

Eso depende, si nunca quieres poder instanciar la clase base, hazla abstracta. De lo contrario, déjelo como una clase normal.

Otros consejos

Si la clase base no debe ser instanciada, entonces conviértala en una clase abstracta; si la clase base necesita ser instanciada, entonces no la haga abstracta.

En este ejemplo, tiene sentido hacer que la clase base sea abstracta ya que la clase base no tiene ningún significado concreto:

abstract class WritingImplement
{
    public abstract void Write();
}

class Pencil : WritingImplement
{
    public override void Write() { }
}

Sin embargo, en el siguiente ejemplo, puede ver cómo la clase base tiene un significado concreto:

class Dog
{
    public virtual void Bark() { }
}

class GoldenRetriever : Dog
{
    public override void Bark() { }
}

En realidad, todo es bastante subjetivo: debe ser capaz de hacer un buen juicio basado en las necesidades de su dominio particular.

Depende, ¿tiene sentido que la clase base en cuestión exista por sí misma sin derivarse de ella? Si la respuesta es sí, entonces debería ser una clase regular, de lo contrario, debería ser una clase abstracta.

Sugiero:

  • Crea una interfaz.
  • Implemente la interfaz en su clase base.
  • Haga que la clase base sea una clase real, no abstracta (vea a continuación por qué).

La razón por la que prefiero clases reales en lugar de clases abstractas es que las clases abstractas no se pueden instanciar, lo que limita las opciones futuras innecesariamente . Por ejemplo, más adelante puede que necesite el estado y los métodos proporcionados por la clase base pero no puedo heredar y no necesito implementar la interfaz; si la clase base es abstracta, no tengo suerte, pero si la clase base es una clase regular, entonces puedo crear una instancia de la clase base y mantenerla como un componente de mi otra clase, y delegar en la instancia para reutilizar estado / métodos proporcionados.

Sí, esto no sucede a menudo, pero el punto es: hacer que el resumen de la clase base evite este tipo de reutilización / solución, cuando no hay razón para hacerlo.

Ahora, si instanciar la clase base sería de alguna manera peligrosa, entonces hazla abstracta, o preferiblemente hazla menos peligrosa, si es posible ;-)

Piense en ello como una cuenta bancaria:

Puede crear una cuenta base de resumen genérica llamada "Cuenta", que contiene información básica como los detalles del cliente.

Entonces puede crear dos clases derivadas llamadas " SavingAccount " o "Cuenta de débito" que puede tener su propio comportamiento específico mientras se beneficia del comportamiento de la clase base.

Esta es una situación en la que el cliente debe tener una cuenta de ahorros o una cuenta de débito, una "Cuenta" genérica no está permitido ya que no es muy popular en el mundo real tener solo una cuenta sin descripción.

Si puede crear un escenario similar para sus necesidades, el resumen es el camino a seguir.

Las clases abstractas son para clases parcialmente implementadas.

Por sí mismo no tiene sentido tener una instancia de una clase abstracta, necesita ser derivada. Si desea poder crear la clase base, no puede ser abstracta.

Me gusta pensar en las clases abstractas como interfaces que tienen algunos miembros predefinidos, ya que son comunes a todas las subclases.

Piensa en esto de una manera diferente

  

¿Es mi clase base un objeto completo por sí misma?

Si la respuesta es no, entonces hazlo abstracto. En caso afirmativo, es probable que desee convertirlo en una clase concreta.

Diría que si no está planeando llamar a la clase base por sí misma, entonces debería definirla como una clase abstracta.

Depende de si desea que la clase base se implemente por sí sola o no.

Como clase abstracta, no puedes hacer objetos a partir de ella.

Las clases abstractas son excelentes para la funcionalidad predefinida, por ejemplo, cuando se conoce el comportamiento mínimo exacto que una clase debe exponer, pero no qué datos debe usar para hacerlo o la implementación exacta.

abstract class ADataAccess
{
    abstract public void Save();
}

Las clases normales (no abstractas) pueden ser excelentes para cosas similares, pero debe conocer los detalles de implementación para poder escribirlas.

public class DataAccess
{
    public void Save()
    {
        if ( _is_new )
        {
            Insert();
        }
        else if ( _is_modified )
        {
            Update();
        }
    }
}

Además, puede usar interfaces (individualmente o en clases, ya sea abstractas o no) para definir el mismo tipo de definición de prototipo.

interface ISaveable
{
    void Save();
    void Insert();
    void Update();
}

class UserAccount : ISavable
{
    void ISavable.Save() { ... }
    void ISavable.Insert() { ... }
    void ISavable.Update() { ... }
}

Otra opción más puede ser el uso de genéricos

class GenDataAccess<T>
{
    public void Save()
    {
        ...
    }
}

Todos estos métodos se pueden usar para definir un cierto prototipo para que las clases trabajen. Formas de asegurarse de que el código A puede hablar con el código B. Y, por supuesto, puede mezclar y combinar todo lo anterior a su gusto. No hay una forma correcta definida, pero me gusta definir interfaces y clases abstractas, luego me refiero a las interfaces. De esta forma, se eliminan algunos de los requisitos de pensamiento para "plomería". en clases de nivel superior manteniendo la máxima flexibilidad. (tener interfaces elimina el requisito de usar la clase base abstracta, pero la deja como una opción).

Creo que muchos de ustedes deberían abandonar las clases básicas de OO nuevamente.

El principio básico subyacente en OOA / OOD es abstraer resumen abstracto, hasta que no pueda abstraer más. Si lo que estás viendo es una abstracción, entonces que así sea, eso es lo que tu OOA / OOD ya te dijo. Sin embargo, si te sientas allí preguntándote si " código " debe ser abstracto o no, entonces obviamente no sabe lo que significa el término y debe aprender nuevamente OOA / OOD / OOP básico :-)

Más al punto de que debes aprender Patrones de diseño y Teoría armónica, ¡esto te ayudará inmensamente con tus diseños OO!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top