8. Klassen und Objekte (Teil 2)Unterklassen, Vererbung, abstrakte KlassenIn der Mathematik (auch in der Numerischen Mathematik) hat man es mit
Funktionen zu tun, die reelle Argumente und reelle Werte
haben. Beispiele hierfür sind quadratische Funktionen Zwei verschiedene Funktionen unterscheiden sich im wesentlichen in
ihrer Abbildungsvorschrift, die in Java in naheliegender Weise
durch eine Methode (die wir Die Bildung von Unterklassen mit der Vererbung von Daten und Methoden ist ein ganz wesentlicher Aspekt von OOP. 8.1 Die abstrakte Klasse FunktionextendsAbstrakt heißt eine Klasse, wenn man keine Instanzen von ihr selbst, sondern nur von ihren Unterklassen bilden will. Eine Methode einer abstrakten Klasse heißt abstrakt, wenn ihre genaue Realisierung bis zur Bildung einer Unterklasse aufgeschoben wird. Wir beginnen mit einer ganz einfachen ersten Realisierung einer
abstrakten Klasse abstract class Funktion1{ abstract double getY(double x); }//Ende class Funktion1 class Sinus1 extends Funktion1{ double getY(double x){ return Math.sin(x); }//Ende getY() }//Ende class Sinus1 class AppF1{ public static void main(String[] args){ Sinus1 sinus = new Sinus1(); System.out.println(sinus.getY(Math.PI/2)); }//Ende main() }//Ende AppF1 Das hätten wir ohne das Getrickse mit Unterklassen auch einfacher
haben können: Die Applikationsklasse hätte genügt, wenn man
die dritte Zeile weggelassen und in der vierten
Wichtig ist auch das Schlüsselwort extends zur Deklaration der Klasse als Unterklasse einer anderen Klasse. Gewöhnungsbedürftig ist die Unterscheidung zwischen der
Klasse namens Ein rechnerisches Gegenstück zu einem Funktionsgraphen ist eine
Wertetabelle einer Funktion. Hier betrachten wir solche, die
eine Funktion an gleichabständigen, aufsteigenden Stellen
auswertet. Es genügt hierzu den ersten, den letzten und die
Anzahl (N+1) der Stellen zu kennen. Die folgende Klasse
abstract class Funktion2{ abstract double getY(double x); double[] getWertetabelle(double a, double b, int N) { double[] y=new double[N+1]; for (int i=0;i<N+1;i++) y[i]=getY(a+i*(b-a)/N); return y; }//Ende getWertetabelle() }//Ende class Funktion2 class Sinus2 extends Funktion2{ double getY(double x){ return Math.sin(x); }//Ende getY() }//Ende class Sinus2 class AppF2{ public static void main(String[] args){ Sinus2 sinus = new Sinus2(); int N=10; double[] y=sinus.getWertetabelle(0,1,N); for(int i=0;i<N+1;i++) System.out.println( "x["+i+"]="+(double) i/N+"y["+i+"]="+y[i]); }//Ende main() }//Ende AppF2 Achten Sie darauf, dass die Methode 8.2 Die Überlagerung von Konstruktoren und Methoden in Unterklassensuper()Bisher sind wir in den abstract class Funktion3{ //Daten: double xMin, xMax; //Konstruktor: Funktion3(double xMin, double xMax){ this.xMin=xMin; this.xMax=xMax; } abstract double getY(double x); //vergleiche mit Funktion2.java double[] getWertetabelle(int N){ double[] y=new double[N+1]; for (int i=0;i<N+1;i++) y[i]=getY(xMin+i*(xMax-xMin)/N); return y; }//Ende Wertetabelle() }//Ende class Funktion3 class Sinus3 extends Funktion3{ //Konstruktor: Sinus3(double a, double b){ super(a,b); } double getY(double x){ return Math.sin(x); }//Ende getY() }//Ende class Sinus3 class AppF3{ public static void main(String[] args){ Sinus3 sinus = new Sinus3(0,5); int N=10; double[] y=sinus.getWertetabelle(N); double[] x=new double[N+1]; for (int i=0;i<N+1;i++) { x[i]=sinus.xMin+(sinus.xMax-sinus.xMin)*i/N; System.out.println( "x["+i+"]="+x[i]+" y["+i+"]="+y[i]); }//Ende for }//Ende main() }//Ende AppF3 Sieht die Oberklasse einen Konstruktor vor, muss die Unterklasse ebenfalls einen Konstruktor haben, und dieser muss als erstes mit dem super()-Befehl den Konstruktor der Oberklasse aufrufen. Danch kann der Konstruktor der Unterklasse noch weitere Details festlegen, z.B. zur Auswahl einer Funktion aus einer Funktionenschar: class Sinus4 extends Funktion3{ int n;//Scharparameter Sinus4(double a, double b,int n){ super(a,b); this.n=n; } double getY(double x){ return Math.sin(n*x); }//Ende getY() }//Ende class Sinus4 class AppF4{ public static void main(String[] args){ int n=3; Sinus4 sinus = new Sinus4(0,5,n); int N=10; double[] y=sinus.getWertetabelle(N); double[] x=new double[N+1]; for (int i=0;i<N+1;i++) { x[i]=sinus.xMin+(sinus.xMax-sinus.xMin)*i/N; System.out.println( "x["+i+"]="+x[i]+" y["+i+"]="+y[i]); }//Ende for }//Ende main() }//Ende AppF4 Diese kleine Erweiterung ermöglicht, mittels des Konstruktors
eine Funktion der Funktionenschar Entsprechend kann man auch Methoden der Oberklasse in einer Unterklasse
überlagern (nicht zu verwechseln mit dem
Begriff überladen innerhalb
einer Klasse): Wir nehmen hierzu in die
abstrakte Oberklasse abstract class Funktion5{ double xMin, xMax; Funktion5(double xMin, double xMax){ this.xMin=xMin; this.xMax=xMax; } abstract double getY(double x); double[] getWertetabelle(int N){ double[] y=new double[N+1]; for (int i=0;i<N+1;i++) y[i]=getY(xMin+i*(xMax-xMin)/N); return y; }//Ende getWertetabelle() double getAbleitung(double x){ double h=0.0001; return (getY(x+h)-getY(x))/h;//Differenzenquotient }//Ende getAbleitung() }//Ende class Funktion5 class Sinus5a extends Funktion5{ //getAbleitung() wird nicht überlagert int n; Sinus5a(double a, double b,int n){ super(a,b); this.n=n; } double getY(double x){ return Math.sin(n*x); }//Ende getY() }//Ende class Sinus5a class Sinus5b extends Funktion5{ int n; Sinus5b(double a, double b,int n){ super(a,b); this.n=n; } double getY(double x){ return Math.sin(n*x); }//Ende getY() //Überlagerung: double getAbleitung(double x){ return n*Math.cos(n*x); } }//Ende class Sinus5b class AppF5{ public static void main(String[] args){ //getAbleitung() wird nicht überlagert: Sinus5a sinus5a = new Sinus5a(0,5,3); //getAbleitung() wird überlagert: Sinus5b sinus5b = new Sinus5b(0,5,3); System.out.println( "Näherung: "+ sinus5a.getAbleitung(1.1)); System.out.println( "exakt: "+ sinus5b.getAbleitung(1.1)); }//Ende main() }//Ende AppF5 8.3 Zugriffsrechte (Sichtbarkeit) Teil 2protectedIn allen Beispielklassen dieses Abschnitts werden keine Zugriffsrechte
festgelegt, d.h. es gilt grundsätzlich Sichtbarkeit aller Daten
und Methoden. Dies gilt als programmiertechnisch unfein. Bevorzugt
wird, dass alle Daten nicht öffentlich sind, durch einen
öffentlichen Konstruktor übergeben werden und höchstens
durch eine öffentliche Methode (z.B. Werden die Daten nun als Richtig "bezahlt" macht sich die Verwendung unterschiedlicher Zugriffsrechte erst, wenn ganze Pakete (wie z.B. Javas Grafikpakete) geschrieben werden. Der Benutzer braucht sich dann nur um die öffentlichen Klassen, Daten und Methoden kümmern. Ein gutes Beispiel sind die am Fachbereich Mathematik geschriebenen Black-Box-Programme, die Sie zum Zeichnen von Funktionsgraphen verwenden werden. Hier finden Sie eine Übersicht über alle öffentlichen Klassen, Methoden und Daten dieser Black Box. Weiter mit 9. Zeichnen von (mehreren) Funktionsgraphen
|
![]() ![]() |
Impressum | 2009-03-14, wwwmath (WL) |