¿Alguno de los lenguajes OO es compatible con un mecanismo para garantizar que un método anulado llame a la base?

12

Creo que esta podría ser una característica útil del idioma y me preguntaba si algún idioma ya lo admite.

La idea es si tienes:

class C
  virtual F
     statement1
     statement2

y

class D inherits C
  override F
     statement1
     statement2
     C.F()

Habría una palabra clave aplicada a CF () de modo que eliminar la última línea de código anterior causaría un error de compilación porque dice "Este método se puede anular pero la implementación aquí debe ejecutarse sin importar qué".

    
pregunta Aaron Anodide 26.09.2012 - 05:52

7 respuestas

13

Sí, lo hacen. Se llama modelo escandinavo de OO, se usa, por ejemplo, en Simula (el otro modelo de OO que está muy extendido y se toma como se concede ahora, es el modelo estadounidense). En el modelo escandinavo, usted no está anulando, sino proporcionando sub-comportamiento.

en el método de Superclass foo:

some-code-before
INNER // this is the actual Simula keyword
some-code-after

en el método de Subclase 'foo:

some-code-in-subclass

Si llama al método foo Superclass 'instance', solo suceden some-code-before y some-code-after ( INNER no hace nada), pero si llama a la instancia de Subclass 'instance', lo hace some-code-before , some-code-in-subclass y entonces some-code-after .

    
respondido por el herby 26.09.2012 - 13:59
9

Ningún idioma que conozco obliga a llamar al método anulado. De hecho, algunos idiomas permiten métodos de anulación que no son anulables (como el uso de la palabra clave new en C #). Sin embargo, hay dos maneras de abordar esto.

El primero es crear un método no reversible (por ejemplo, uno que carezca de la palabra clave virtual en C # o uno que tenga la palabra clave final en Java) que llame a una que no se pueda llamar desde fuera de la clase (por ejemplo, protected en C #, Java o C ++).

class C
  A
     statement1
     F
     statement3

  protected virtual F
     statement2

y

class D inherits C

  protected override F
     statement4
     C.F()

Las clases que anulan C son libres de anular F y modificar su comportamiento, pero las personas que llaman fuera de la clase solo acceden a ella a través de A .

Editar: Como han señalado otros, esto se denomina Patrón de método de plantilla .

La segunda forma es usar un lenguaje que imponga condiciones previas y postcondiciones especificadas en la clase base, como Eiffel o C # con contratos de código. No forzará que se llame a la clase base, pero el método anulado puede ser forzado a realizar las mismas declaraciones. El uso de aspectos también puede ayudar si el idioma permite que se hereden aspectos.

    
respondido por el akton 26.09.2012 - 07:33
7

No es realmente parte del lenguaje, pero el analizador de código estático FindBugs para Java tiene una anotación OverrideMustInvoke que un desarrollador puede agregar a un método, y que hará que FindBugs muestre un error si encuentra un método de reemplazo que no llame a la súper implementación. Incluso permite especificar si la llamada debe ser la primera o la última en el método de anulación.

    
respondido por el Michael Borgwardt 26.09.2012 - 09:49
6

Requerir llamar a un método de superclase es un antipatón . Si no se aplica en tiempo de compilación, es propenso a errores, por lo que está buscando un constructo de lenguaje que lo verifique.

Hay una forma que se admite en todos los idiomas de OO: el patrón de método de plantilla . Aquí, hace que el método de superclase no sea anulable, y en él se llama un método anulable. La subclase puede anular este método para agregar funcionalidad:

class super {
  public final void doSomething() {
    doSpecialthing();
    doMore();
  }
  public void doSpecialthing() {
  }
}

Dependiendo de la ubicación de la llamada al método anulado, incluso permite determinar el orden de ejecución, que con la súper llamada ordinaria es a voluntad del implementador de la subclase.

    
respondido por el Ozan 26.09.2012 - 14:28
1

El patrón más cercano en el que puedo pensar es en eventos auto-suscritos. Es un poco engorroso, y en absoluto intuitivo para el programador, pero logra el objetivo.

class C
{
    public void F()
    {
        ...
        OnF()
    }

    protected event OnF
}

class D : C
{
    public D()
    {
        base.OnF += this.F
    }

    private void F
    {
        ...
    }
}
    
respondido por el Hand-E-Food 26.09.2012 - 06:53
1

Los "sabores" de la máquina Lisp permitían los métodos con el tipo "antes" "después" y "alrededor" de los heredados método principal.

    
respondido por el ddyer 26.09.2012 - 19:38
0

Aunque no es una mala idea en teoría, tiene el efecto secundario negativo de restringir mis opciones al implementar D . Por ejemplo, qué pasa si (por algún motivo insondable), es más conveniente llamar a la implementación de superclase de F desde algún otro método:

class D inherits C
    override F
        statement1
        statement2
        G()
    G
        statement3
        C.F()
        statement4

Bajo tu escenario, imagino que el compilador marcaría la implementación de F en D , aunque sí (indirectamente) llame a C.F() .

Básicamente, lo que has descrito es un posible mecanismo para ayudar al compilador a reconocer cuando se viola un contrato en clases que heredan de C . Mi punto es que, si bien eso es una gran cosa, no debería ser a costa de limitar cómo puedo implementar mi subclase.

    
respondido por el Mac 26.09.2012 - 06:32

Lea otras preguntas en las etiquetas