Qualche lingua OO supporta un meccanismo per garantire che un metodo sottoposto a override chiamerà la base?

12

Penso che questa potrebbe essere una funzionalità linguistica utile e mi chiedevo se alcune lingue lo supportano già.

L'idea è se hai:

class C
  virtual F
     statement1
     statement2

e

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

Ci sarebbe una parola chiave applicata a CF () in modo tale che rimuovere l'ultima riga di codice sopra causerebbe un errore del compilatore perché sta dicendo "Questo metodo può essere sovrascritto ma l'implementazione qui deve essere eseguita indipendentemente da cosa".

    
posta Aaron Anodide 26.09.2012 - 05:52
fonte

7 risposte

13

Sì, lo fanno. Si chiama modello scandinavo di OO, è usato ad esempio in Simula (l'altro modello OO che è diffuso e preso come scontato ora è il modello americano). Nel modello scandinavo, non si sta ignorando, ma si fornisce un sotto-comportamento.

nel metodo di Superclass foo:

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

nel metodo fo della sottoclasse:

some-code-in-subclass

Se chiami il metodo delle istanze Superclass pippo, solo some-code-before e some-code-after avvengono ( INNER non fa nulla), ma se chiami Subclass 'istanze' pippo, fa some-code-before , some-code-in-subclass e then some-code-after .

    
risposta data 26.09.2012 - 13:59
fonte
9

Nessuna lingua che conosco applica forzatamente il metodo sovrascritto. In effetti, alcuni linguaggi consentono metodi di sovrascrittura che non sono sovrascrivibili (come l'utilizzo della parola chiave new in C #). Tuttavia, ci sono due modi per affrontarlo.

Il primo è quello di creare un metodo non sostituibile (ad esempio quello che manca la parola chiave virtual in C # o quella che ha la parola chiave final in Java) che chiama una chiave sovrascrivibile che non può essere chiamata al di fuori della classe (es. protected in C #, Java o C ++).

class C
  A
     statement1
     F
     statement3

  protected virtual F
     statement2

e

class D inherits C

  protected override F
     statement4
     C.F()

Le classi che sovrascrivono C sono libere di eseguire l'override di F e modificarne il comportamento, ma i chiamanti esterni alla classe accedono solo tramite A .

Modifica: come altri hanno sottolineato, questo è chiamato modello di metodo Template .

Il secondo modo è usare un linguaggio che imponga le condizioni preliminari e postcondizionate specificate nella classe base, come Eiffel o C # con Contratti di codice. Non imporrà la chiamata alla classe base ma il metodo sottoposto a override può essere forzato ad eseguire le stesse istruzioni. L'utilizzo degli aspetti può essere d'aiuto anche se la lingua consente l'ereditarietà degli aspetti.

    
risposta data 26.09.2012 - 07:33
fonte
7

Non fa realmente parte della lingua, ma l'analizzatore di codice statico di FindBugs per Java ha un'annotazione OverrideMustInvoke che uno sviluppatore può aggiungere a un metodo e che farà sì che FindBugs mostri un errore se trova un metodo di override che non chiama la super implementazione. Permette anche di specificare se la chiamata deve essere la prima o l'ultima nel metodo di sovrascrittura.

    
risposta data 26.09.2012 - 09:49
fonte
6

Il requisito per chiamare un metodo di superclasse è un anti-pattern . Se non viene applicato in fase di compilazione, è soggetto a errori, motivo per cui si sta cercando un costrutto linguistico che ne verifichi la presenza.

Esiste un modo supportato in tutte le lingue OO: il modello di metodo del modello . Qui, si rende il metodo della superclasse non sovrascrivibile e in esso si chiama un metodo sovrascrivibile. La sottoclasse quindi può sostituire questo metodo per aggiungere funzionalità:

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

A seconda della posizione della chiamata al metodo sovrascritto, consente anche di determinare l'ordine di esecuzione, che con la normale super chiamata è a discrezione dell'attore della sottoclasse.

    
risposta data 26.09.2012 - 14:28
fonte
1

Il modello più vicino a cui riesco a pensare è quello degli eventi autoprogrammati. È un po 'macchinoso, e per nulla intuitivo per il programmatore, ma raggiunge l'obiettivo.

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

    protected event OnF
}

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

    private void F
    {
        ...
    }
}
    
risposta data 26.09.2012 - 06:53
fonte
1

I "sapori" della macchina Lisp consentivano i metodi con tipo "prima" "dopo" e "intorno" l'ereditato metodo principale.

    
risposta data 26.09.2012 - 19:38
fonte
0

Sebbene non sia una cattiva idea in teoria, ha l'effetto collaterale negativo di limitare le mie opzioni quando si implementa D . Ad esempio, cosa succede se (per qualche motivo insondabile), è più comodo chiamare l'implementazione della superclasse di F da qualche altro metodo:

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

Sotto il tuo scenario, immagino che il compilatore possa segnalare l'implementazione di F in D , anche se chiama (indirettamente) C.F() .

Fondamentalmente, quello che hai descritto è un possibile meccanismo per aiutare il compilatore a riconoscere quando un contratto sulle classi che ereditano da C viene violato. Il mio punto è che, mentre questa è una cosa grandiosa, non dovrebbe andare a scapito di limitare come posso implementare la mia sottoclasse.

    
risposta data 26.09.2012 - 06:32
fonte

Leggi altre domande sui tag