Pure abstract Classes oder Interfaces

sind Klassen die nur pure virtual functions enthalten.

Das erscheint erstmal ziemlich sinnlos, wozu soll Klasse, die nichts implementiert, gut sein?

Eine pure abstract class macht Vorschriften, d.h. Klassen, die davon erben, sind gezwungen die vorgegebenen Methoden zu implementieren.

Bei grossen, komplexen Projekten von 1,000,000 Zeilen code ist ein Hauptproblem die Definition einheitlicher Schnittstellen zur Kommunikation der einzelnen Komponenten und die Minimierung von Abhängigkeiten. Dafür ist das Konzept der pure abstract class oder interface in Java, das einheitliches Verhalten erzwingt, extrem hilfreich.


Interfaces als Funktions-Platzhalter in der Numerik

In der Numerik tritt es häufig auf, dass man einen allgemeinen Algorithmus implementieren möchte, den man auf viele Fälle ( beliebige Funktionen) anwenden möchte. Z.B. Nullstellenbestimmung (Bisektion, Gauss-Newton), numerische Integration (Trapez, Simpson), ...

In Fortran/C löst man sowas mit function-pointers das sind ziemlich unangenehme, schwer verständliche Konstrukte.

In C++/JAVA/OO lässt sich das elegant und einfach mit interfaces (bzw. pure abstract class) lösen:



#include <cmath>

class  Func { // pure abstract class
public:
  virtual double value( double x) = 0; 
};

class Nullstelle { 
  // class with just one method
public:
  // finde Nullstelle von f nach Bisektionsverfahren
  // f ist Objekt das interface Func implementiert, d.h. eine Methode double value(double) hat
  double find( double x1, double x2, Func &f ) {
    double f1 = f.value(x1);
    double f2 = f.value(x2);
    double xn = x1;
    double fn = f1;
    for ( int i=0; i<1000 && fabs(fn) > 1e-6; i++ ) {  // Abbruch nach 1000 Iterationen oder bis auf 1e-6 an Nullstelle
      xn = (x1+x2)/2.;         // Neues x in Mitte
      fn = f.value(xn);        // Funktionswert dazu
      if ( fn*f2 > 0. ) {      // gleiches Vorzeichen wir f2 ?
    x2 = xn;             
    f2 = fn;             // dann ersetze x2,f2
      }
      else {
    x1 = xn;             // andernfalls x1,f1
    f1 = fn;
      }
    }
    return( xn );
  }
};



Das Programm in Klasse Nullstelle weiss nicht's über die eigentliche Funktion die es benutzt, es kennt nur die pure abstract class Func.

Erst bei Aufruf von ns.find(...) in einem Anwendungsprogramm wird festgelegt welches Objekt gerufen wird:



#include <iostream>
#include <cmath>
#include "Nullstelle.cpp"

using namespace std;

class TFunc1 : public Func { // concrete class 1
public:
  double value( double x) { // define method
    return( cos(x) -x);
  }
};
class TFunc2 : public Func { // concrete class 2
public:
  double value( double x) { // define method
    return( exp(x) -x);
  }
};
int main() {    
  double x1 = 0., x2 = 1.6; // Startintervall
  TFunc1 t1;
  TFunc2 t2;
  Nullstelle ns;
  cout << "Nullstelle = " << ns.find( x1, x2, t1 ) << endl;
  cout << "Nullstelle = " << ns.find( x1, x2, t2 ) << endl;
}



GDuckeck 2019-08-01