# Array mit Set- und Get-Methoden?



## schrobi (11. Dez 2009)

Guten Tach zusammen.

Ich sitz seit gestern an einer Aufgabe und momentan fehlt mir irgendwie das Verständnis, was bzw. wie ich das lösen soll...

Also die Aufgabe besteht daraus eine Matrixmultiplikation mit Hilfe von drei Klassen zu erstellen. Eine Testklasse, eine Klasse die die Rechenarbeit übernimmt und dann noch eine Klasse Matrix in welcher eine Methode zeigeMatrix() vorkommt.

Jetzt kommen die zwei Stellen bei denen ich Probleme habe.

1. In der klasse Matrix sollen set- und get-methoden eingebaut werden.

2. in der Klasse die die Berechnung durchführt soll folgende Methode rein:
    static Matrix calculateProduct(Matrix A, Matrix B)

Mein bisheriger Code ist folgender:

```
public class Matrix {

	int[][] matrixA = {
		{1, 2, 3},
		{4, 5, 6},
		{7, 8, 9}
	};


    public void zeigeMatrix() {
        for (int i = 0; i < matrixA.length; i++) {
		    for (int j = 0; j < matrixA[0].length; j++) {
		        System.out.print(matrixA[i][j] + "\t");
		    }
		    System.out.println();
		}
    }

}
```


```
public class MatrixMath {

	static int[][] Matrix = new int[3][3];

    int[][] matrixB = {
		{6, -1, -2},
		{3, 2, -4},
		{0, 3, -8}
	};


    static Matrix calculateProduct(Matrix A, Matrix B) {

		return ?;
	}
```


```
public class MatrixTest {


    public static void main(String[] args) {
        Matrix matr = new Matrix();
		MatrixMath matrM = new MatrixMath();

        matr.zeigeMatrix();
        calculateProduct(Matrix A, Matrix B);

    }

}
```

Ich habe aber das Gefühl, dass ich auf dem falschen Weg bin. Da ich ja einfach nur das eine Array ausgebe. Wahrscheinlich soll nur das Ergebnisarray ausgegeben werden... 

Ich hoffe ihr könnt mir hier einen Schubs in die richtige Richtung geben. 

schrobi


----------



## Michael... (11. Dez 2009)

schrobi hat gesagt.:


> Ich habe aber das Gefühl, dass ich auf dem falschen Weg bin.


Würde jetzt nicht sagen, dass Du auf dem falschen Weg bist.
In der Klasse Matrix fehlen Dir halt noch die set und get Methode - man kann ihr auch noch einen Konstruktor spendieren.

```
class Matrix {
	private int[][] matrix = new int[][]{{0}};
		
	public void zeigeMatrix() {
		//hast Du ja bereits implementiert
	}
		
	public void setMatrix(int[][] matrix) {
		this.matrix = matrix;
	}
		
	public int[][] getMatrix() {
		return matrix;
	}
}
```
Und in der Klasse MatrixMath musst Du halt noch die calculateProduct(...) implementieren.
Dieses int[][] matrixB hat da eigentlich nichts zu suchen.
Die main in der Testklasse könnte dann so aussehen:

```
public static void main(String[] args) {
	Matrix a = new Matrix();
	a.setMatrix(new int[][]{{1, 2},{3, 4}});
	Matrix b = new Matrix();
	b.setMatrix(new int[][]{{5, 6},{7, 8}});
	
	Matrix product = MatrixMath.calculateProduct(a, b);
	product.zeigeMatrix();
}
```


----------



## Marco13 (11. Dez 2009)

Naja, bisher ist nicht viel falsch... In der Klasse "Matrix" sollte es halt noch eine Methode geben
public int get(int row, int column)
die den entsprechenden Array-Eintrag liefert, und eine Methode
public void set(int row, int column, int value)
die den Eintrag setzt.

Die MatrixMath-Klasse braucht intern nicht dieses "matrixB" - sie kriegt die beiden Matrizen, die sie multiplizieren soll, ja in der Methode übergeben....

EDIT: Ja, WELCHE set/get-Methoden es geben soll, ist halt nicht gesagt worden...


----------



## SlaterB (11. Dez 2009)

evtl. soll man mit set und get einzelne Felder abfragen können und setzen, dann braucht man auch noch Länge und Breite,
damit könnten alle Berechnungen durchgeführt werden, ohne den internen Aufbau der Matrix zu kennen,
ob Array oder List hätte dann keinen Einfluß mehr


----------



## schrobi (11. Dez 2009)

Hallo Leute,

vielen Dank für die Antworten. Ich werde da nachher nochmal reingucken da seit 17Uhr die Nachbarskids hier sind und wir Babysitten müssen.

Also dann bis morgen.

schrobi


----------



## schrobi (13. Dez 2009)

Hallo.
Nochmals danke für Eure Antworten.

@SlaterB: Es wird in der Aufgabe nur von einer m x n Matrix gesprochen. eine Beispielmatrix ist eine 3*3 also denke ich mal, dass hier auch eine 3*3 Matrix verlangt wird.

@Michael...: Das sieht ja schon ne Ecke besser aus als mein wirres Zeug . Wenn ich das nun richtig gesehn habe fehlt nun nurnoch der Methodenrumpf zu calculateProduct() oder hab ich noch was übersehen? 

@Marco13: Mit den Set- und Get-Methoden ist das glaub ich so richtig was Micheal... geschrieben hat, da diese ja in der Klasse Matrix gefordert waren.

So, ich köchel dann mal an der calculateProduct() rum.. Es ist aber bestimmt nur eine Frage der Zeit bis ich mich hier wieder melde 

schrobi


----------



## Marco13 (13. Dez 2009)

schrobi hat gesagt.:


> @Marco13: Mit den Set- und Get-Methoden ist das glaub ich so richtig was Micheal... geschrieben hat, da diese ja in der Klasse Matrix gefordert waren.



Wenn der zweite Teil des Satzes eine Begründung sein sollte, ist die ungültig: Die Methoden, die ich angedeutet hatte, lägen ja auch in der Klasse "Matrix" - und hätten den Vorteil, den SlaterB schon erwähnt hat: Es wäre egal, wie die Matrix intern aufgebaut ist... (das kann zwar auch bei den anderen Methoden egal sein, wäre aber deutlich un-eleganter...)


----------



## schrobi (13. Dez 2009)

Hi Marco,

bitte nicht falsch verstehen. Ich wollte keineswegs sagen, dass das was Du geschrieben hast falsch ist oder nicht so "toll" wie das was Micheal... geschrieben hat. Wollte damit nur andeuten dass Michaels Schreibweise bzw. Bezeichnungen eher dem entspricht was ich "brauche". 

schrobi


----------



## Marco13 (13. Dez 2009)

So habe ich das auch nicht aufgefasst. Und selbst wenn, dann würde ich da drüber stehen :smoke: 


"Brauchen" tust du das nicht. Es ist nunmal so, dass es selten bis nie sinnvoll ist, den internen Zustand eines Objektes in der Form nach draußen sichtbar (und zugreifbar) zu machen, wie das z.B. mit der Methode
[c]public int[][] getMatrix() {  return matrix;  }[/c]
gemacht wird. Jeder kann sich diesen Array holen, dann ganz brutal

```
int array[][] = matrix.getMatrix();
array[0] = null;
matrix.zeigeMatrix();
```
aufrufen, und sich über einen bunten StackTrace freuen. Es gibt so ein paar Dinge, die nichts mit einem willkürlich-unfundiert-subjektiven "Ich mach' das halt mal so (weil ich es gerade so 'brauche'  )" zu tun haben, sondern die designtechnische Gründe und Rechtfertigungen haben. Aber jedem steht es frei, solche Dinge so zu implemetieren, wie er es für richtig hält...


----------



## schrobi (13. Dez 2009)

Ich möchte mir ja auch keinen "schlechten Programmierstil" angewöhnen und jag meine fertigen Programme immer schön duch einen Checkstyle-o-mat (ich weiss, sowas wird er wohl nicht bemängeln, aber der Wille ist da ). Aber im Moment weiss ich es einfach nicht besser und kann da noch nicht so gut unterscheiden was wirklich sinnvoll ist und was nicht.

So, nun habe ich aber mal wieder eine Frage zu meiner schönen MatrixMath Klasse. Hoffe du steinigst mich gleich nicht...

Habe eben folgendes implementiert aber bin nicht sicher ob es so richtig ist mit der matrC. Die müsste ich ja eigentlich erstmal erstellen aber das soll ja die Methode machen oder? Also das ist erstmal die berechnung der Kreuzproduktes zweier Matrizen. 



```
public class MatrixMath {

	static Matrix calculateProduct(Matrix A, Matrix B) {
		matrC[0][0] = (matrA[0][0] * matrB[0][0] + matrA[0][1] * matrB[1][0] + matrA[0][2] * matrB[2][0]);
		matrC[1][0] = (matrA[1][0] * matrB[0][0] + matrA[1][1] * matrB[1][0] + matrA[1][2] * matrB[2][0]);
		matrC[2][0] = (matrA[2][0] * matrB[0][0] + matrA[2][1] * matrB[1][0] + matrA[2][2] * matrB[2][0]);

		matrC[0][1] = (matrA[0][0] * matrB[0][1] + matrA[0][1] * matrB[1][1] + matrA[0][2] * matrB[2][1]);
		matrC[1][1] = (matrA[1][0] * matrB[0][1] + matrA[1][1] * matrB[1][1] + matrA[1][2] * matrB[2][1]);
		matrC[2][1] = (matrA[2][0] * matrB[0][1] + matrA[2][1] * matrB[1][1] + matrA[2][2] * matrB[2][1]);

		matrC[0][2] = (matrA[0][0] * matrB[0][2] + matrA[0][1] * matrB[1][2] + matrA[0][2] * matrB[2][2]);
		matrC[1][2] = (matrA[1][0] * matrB[0][2] + matrA[1][1] * matrB[1][2] + matrA[1][2] * matrB[2][2]);
		matrC[2][2] = (matrA[2][0] * matrB[0][2] + matrA[2][1] * matrB[1][2] + matrA[2][2] * matrB[2][2]);


		return new Matrix();
	}

}
```

Ist das so der richtige Weg oder eher nicht?
Weiss irgendwie grad nicht weiter.

schrobi


----------



## schrobi (13. Dez 2009)

Ist es richtig wenn ich das so schreib?

```
static Matrix calculateProduct(matrA, matrB)
```
und am Ende dann

```
return new Matrix(matrC);
```
 
Bekomme dann aber einen Compilerfehler der jeweils auf matrA, matrB zeigt mit der info <identifier> expected

Komme da nicht weiter. Wär nett wenn sich nochmal jemand meiner annehmen würde 

@Marco13 
Wie könnte ich dies 

```
public int[][] getMatrix() {
        return matrix;
    }
```
denn eleganter schreiben? Reicht ja sicherlich nicht wenn ich einfach public in private tausch.


schrobi


----------



## ThreadPool (13. Dez 2009)

schrobi hat gesagt.:


> Wie könnte ich dies
> 
> ```
> public int[][] getMatrix() {
> ...



Es geht dabei nicht um "Eleganz", sondern um verschiedene Konzepte der objektorientierten Programmierung. Beim "Verbergen" der Implementation und der Art wie ein Objekt seine Aufgabe erfüllt geht es darum "Grenzen" festzulegen die von den Beteiligten nicht übertreten werden (können). Stell dir mal vor jeder Verwender deines Objekts könnte unkontrolliert am "inneren" Zustand des Objekts rumspielen, dass wäre doch ein einziges Chaos.

Das Problem mit dem Code oben ist das du dein "inneren" Zustands des Objektes nach aussen "publizierst", das ist ja noch nicht mal schlimm, es ist vielmehr die Art "wie" du das tust. Du gibst nämlich eine Referenz auf einen wichtigen Teil des Objekts heraus, so erhält jeder Client die Möglichkeit ungehindert daran rumzuspielen. Eine Möglichkeit das zu beheben wäre eine Kopie der eigentlich "inneren" Matrix zurückzugeben.

Das ist am Ende aber eine Designfrage und hängt stark von der weiteren Verwendung ab.


----------



## schrobi (13. Dez 2009)

Hi ThreadPool,

danke für dein Antwort.
Meinst du mit Kopie eine Instanz der Klasse Matrix oder ein "Clone" des Arrays?
Ich komme grad nicht ganz mit.

schrobi


----------



## ThreadPool (13. Dez 2009)

schrobi hat gesagt.:


> Meinst du mit Kopie eine Instanz der Klasse Matrix oder ein "Clone" des Arrays?



Ich meine damit einen "Clon" des Arrays. Du solltest aber überlegen ob es überhaupt nötig ist die Matrix in irgendeiner Form herauszugeben. Braucht die Informationen überhaupt irgendjmd?


----------



## schrobi (13. Dez 2009)

Hm, also ausgegeben werden soll ja nur die Ergebnismatrix. Also MatrixA x MatrixB.

Irgendwie bekomm ich das nicht auf die Reihe mit den gettern und settern. Zwar steht in jedem Buch, dass die dazu da sind, vor unbefugtem Zugriff zu schützen aber ich werd nich grün mit denen.

Also frag ich jetzt mal so geradeheraus. Wie wird das hier mit dem get und set implementiert? Ich habe versucht mittels 
	
	
	
	





```
matrix.getMatrix();
```
 in der MatrixMath Klasse zu arbeiten aber das geht nicht.. 

schrobi


----------



## Painii (13. Dez 2009)

Ein ordentlicher getter verhindert sowas:

```
public class A{
 public static Object a = new String("hallo");
 private static Object b = new String("welt");
 public static getB(){
  return b.clone(); //müsste dann entsprechend gebaut sein, dass man nichtsmehr verändern kann
 }
}
public class B{
 public static void main(String[] args){
  A.a=null;
  A.getB()=null; //A.b bleibt aber trotzdem erhalten
 }
}
```

Bei settern kannst du entsprechende Regeln auch einführen... wenn du einen Geldbetrag setzen willst kannst du ja z.b. festlegen dass der Geldbetrag positiv sein muss.


----------



## ThreadPool (13. Dez 2009)

schrobi hat gesagt.:


> Hm, also ausgegeben werden soll ja nur die Ergebnismatrix. Also MatrixA x MatrixB.
> 
> Irgendwie bekomm ich das nicht auf die Reihe mit den gettern und settern. Zwar steht in jedem Buch, dass die dazu da sind, vor unbefugtem Zugriff zu schützen aber ich werd nich grün mit denen.
> 
> ...



Naja wahrscheinlich bist du jetzt verwirrter als vorher. Lassen wir also erstmal guten Stil beiseite und versuchen was funktionierendes auf die Beine zu stellen. Falls du die Funktion calculateProduct wie um 17:32 genommen hast wirst du damit nicht glücklich. Es müsste schon ungefähr wie folgt aussehen.



```
public staticMatrix multiply(Matrix a, Matrix b){
		int[][] matrA = a.getMatrix();
		int[][] matrB = b.getMatrix();
		
		int[][] matrC = new int[3][3];
		
		matrC[0][0] = (matrA[0][0] * matrB[0][0] + matrA[0][1] * matrB[1][0] + matrA[0][2] * matrB[2][0]);
        matrC[1][0] = (matrA[1][0] * matrB[0][0] + matrA[1][1] * matrB[1][0] + matrA[1][2] * matrB[2][0]);
        matrC[2][0] = (matrA[2][0] * matrB[0][0] + matrA[2][1] * matrB[1][0] + matrA[2][2] * matrB[2][0]);
 
        matrC[0][1] = (matrA[0][0] * matrB[0][1] + matrA[0][1] * matrB[1][1] + matrA[0][2] * matrB[2][1]);
        matrC[1][1] = (matrA[1][0] * matrB[0][1] + matrA[1][1] * matrB[1][1] + matrA[1][2] * matrB[2][1]);
        matrC[2][1] = (matrA[2][0] * matrB[0][1] + matrA[2][1] * matrB[1][1] + matrA[2][2] * matrB[2][1]);
 
        matrC[0][2] = (matrA[0][0] * matrB[0][2] + matrA[0][1] * matrB[1][2] + matrA[0][2] * matrB[2][2]);
        matrC[1][2] = (matrA[1][0] * matrB[0][2] + matrA[1][1] * matrB[1][2] + matrA[1][2] * matrB[2][2]);
        matrC[2][2] = (matrA[2][0] * matrB[0][2] + matrA[2][1] * matrB[1][2] + matrA[2][2] * matrB[2][2]);
        Matrix ret = new Matrix();
        ret.setMatrix(matrC);
		return ret;
	}
```

Wobei dein getMatrix eine Referenz zurückliefert also so aussieht:
	
	
	
	





```
public int[][] getMatrix() {
        return matrix;
    }
```

Und dein setMatrix wie folgt aussehen sollte:


```
public void setMatrix(int[][] matrixData){
		for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                matrix[i][j] = matrixData[i][j];
	}
```

Das setMatrix setzt natürlich voraus das du innerhalb deiner Matrix-Klasse einen gültigen Speicherbereich der Größe 3x3 des Typs int zur Verfügung gestellt hast. Im Beispiel wäre das 
	
	
	
	





```
int matrix[][] = new int[3][3];
```


----------



## Marco13 (13. Dez 2009)

schrobi hat gesagt.:


> Ich möchte mir ja auch keinen "schlechten Programmierstil" angewöhnen und jag meine fertigen Programme immer schön duch einen Checkstyle-o-mat (ich weiss, sowas wird er wohl nicht bemängeln, aber der Wille ist da ).



EIN Checkstyle-o-mat - welchen denn? Sowas wie PMD oder .. ich glaub' auch FindBugs würden dir nämlich so einen nach draußen gegebenen Array mit einer Meldung wie "Exposed Internal State" (oder ähnlich) um die Ohren hauen  Ob CheckStyle das auch macht - weiß ich nicht .... sollte es aber 



schrobi hat gesagt.:


> So, nun habe ich aber mal wieder eine Frage zu meiner schönen MatrixMath Klasse. Hoffe du steinigst mich gleich nicht...



Für eine Frage werde ich dich nicht steinigen. Gesteinigt wirst du nur, wenn du Wein trinkst. Bin ja kein Unmensch :joke: Die Implementierung ist an sich nicht ganz falsch ... ThreadPool hat ja schon was dazu gesagt...Aber ... bist du sicher, dass das NUR für 3x3-Matrizen funktionieren soll? Also, sofern das nicht explizit in der Aufgabenstellung steht, musst du wohl davon ausgehen, dass das _eigentlich_ für allgemeine Matrizen, mit 3 Schleifen gemacht werden sollte. Aber das für den 3x3-Fall mal so aufzuschreiben kann selbst dafür nicht schaden: Damit kann man sich leichter erarbeiten, wie diese 3 Schleifen dann aussehen müssen, und man kann seine Implementierung damit ggf. überprüfen.


----------



## schrobi (14. Dez 2009)

Hallo ihr zwei.

@ThreadPool

Ich habe mein MatrixMath nun erstmal so umgeschrieben wie Du es vorgeschlagen hast. Er kompiliert auch fehlerfrei. Nun habe ich eine Frage zu der Klasse Matrix. Dort habe ich nun auch die set und get Methoden angepasse allerdings brauche ich nun noch eine Methode zeigeMatrix() welche dann die Ergebnismatrix ausgibt. Dein setMatrix sieht für mich schonmal nach dieser "Ausgabeschleife" aus. Nun habe ich aber noch folgende MatrixTest beibehalten

```
public static void main(String[] args) {

	    Matrix matrA = new Matrix();
	    matrA.setMatrix(new int[][]{{1, 2, 3},{4, 5, 6},{7, 8, 9}});
	    Matrix matrB = new Matrix();
	    matrB.setMatrix(new int[][]{{6, -1, -2},{3, 2, -4},{0, -3, -8}});

	    Matrix product = MatrixMath.calculateProduct(matrA, matrB);
	    product.zeigeMatrix();
	}
```

Gehe ich Recht in der Annahme, dass hier das zeigeMatrix() in der MatrixMath gesucht wird? Wenn ich das nämlich ausführe bekomme ich keine Ausgabe.

schrobi


----------



## ThreadPool (14. Dez 2009)

schrobi hat gesagt.:


> Gehe ich Recht in der Annahme, dass hier das zeigeMatrix() in der MatrixMath gesucht wird? Wenn ich das nämlich ausführe bekomme ich keine Ausgabe.



Nein du rufst die zeigeMatrix() an der "neu" erstellten Matrix auf, welche durch MatrixMath.calculateProduct() erstellt wurde. Das gar nichts ausgegeben wird ist etwas eigenartig. Sieht deine Ausgabefunktion ungefähr so aus?

```
//nur für 3x3 Matrizen
public void zeigeMatrix() {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            System.out.print(matrix[i][j] + "\t");
        }
        System.out.println();
    }
}
```


----------



## schrobi (14. Dez 2009)

Ach bin ich doof :lol:

ich hatte die zeigeMatrix() auskommentiert weil ich durch deine setMatrix verwirrt war. Da ist ja beinahe die gleiche schleife drin wie bei zeigeMatrix nur eben ohne System.out.print.. kein wunder dass nix rauskommt.
Aber nun läufts endlich wie es soll! :applaus:

Hätte aber noch eine Verständnisfrage zu dieser Set-Methode.
Ich denke mir, dass die schleife darin dazu ist die 3*3 Matrix zu erstellen. Ist das richtig? Weil ich dachte eigentlich dass die Matrix bzw das Array in der Matrixklasse mittels 
	
	
	
	





```
int matrix[][] = new int[3][3];
```
 erstellt, und in der Testklasse mit 
	
	
	
	





```
matrA.setMatrix(new int[][]{{1, 2, 3},{4, 5, 6},{7, 8, 9}});
	    
	    matrB.setMatrix(new int[][]{{6, -1, -2},{3, 2, -4},{0, -3, -8}});
```
 mit Werten gefüllt wird. Ich seh schon mit Get und Set muss ich mich noch auseinandersetzen. Gibts da irgendwo hilfreiche Seiten mit Beispielen oder sowas?

Nun nochmal ein DANKE an alle die hier mitgeholfen haben. :toll:

schrobi


----------



## ThreadPool (14. Dez 2009)

schrobi hat gesagt.:


> Hätte aber noch eine Verständnisfrage zu dieser Set-Methode.
> Ich denke mir, dass die schleife darin dazu ist die 3*3 Matrix zu erstellen. Ist das richtig?



Die set-Methode so wie sie da steht "kopiert" die Werte eines übergebenen Arrays in das interne Matrix-Array. Bevor du dich zu sehr freust, jetzt ist es eigentlich an der Zeit den Code wegzuwerfen und nochmal von vorne zu beginnen.


----------



## schrobi (14. Dez 2009)

achso. Ich war etwas verwirrt wo denn aufmal das matrixData in der Schleife herkam.

Das alles nochmal auf eigene Faust zu machen ist zweifelsfrei das Beste und ich werde mich auch nachher daran versuchen aber es ist immer gut zu Wissen, dass man für den Fall der Fälle eine funktionierende Version in Petto hat 

Dank Dir nochmal für Deine Geduld.

schrobi


----------

